From addf1b3d64337501e01f872ff6740fbf657ebff2 Mon Sep 17 00:00:00 2001 From: Mohan Dholu <54059494+mohandholu43@users.noreply.github.com> Date: Tue, 7 Jan 2025 17:38:41 +0530 Subject: [PATCH] Feature/custom dns tab (#483) * custom dns for public for icon * custom dns * custom dns add tab other ui change for in * custom dns add status chips * bug fix in border color bg color * border shadow add * all elint and other fix * remove unuse * commit fix done * icon fix * circle icon fix * remove rect * fix in custom dns multiple show --- .../[resourceId]/[resourceInstanceId].js | 42 +- .../CustomStatusChips/CustomStatusChips.tsx | 57 +++ .../AlertTrianglePITR/AlertTrianglePITR.jsx | 26 ++ .../CircleCheck/CircleCheckWithBorderIcon.jsx | 31 ++ src/components/Icons/DNSIcon/PrivateIcon.tsx | 131 ++++++ src/components/Icons/DNSIcon/PublicIcon.tsx | 180 ++++++++ .../Connectivity/ConnectivityCustomDNS.tsx | 40 +- .../Connectivity/ConnectivityEndpoint.tsx | 21 + .../Connectivity/CustomDNS.tsx | 389 ++++++++++++++++++ .../Connectivity/CustomDNSDetails.tsx | 175 ++++++++ .../Connectivity/CustomDNSDetailsModal.tsx | 98 ----- .../Connectivity/CustomDNSEndPoint.tsx | 91 ++++ .../Connectivity/ResourceCustomDNS.tsx | 130 ++++++ 13 files changed, 1280 insertions(+), 131 deletions(-) create mode 100644 src/components/CustomStatusChips/CustomStatusChips.tsx create mode 100644 src/components/Icons/AlertTrianglePITR/AlertTrianglePITR.jsx create mode 100644 src/components/Icons/CircleCheck/CircleCheckWithBorderIcon.jsx create mode 100644 src/components/Icons/DNSIcon/PrivateIcon.tsx create mode 100644 src/components/Icons/DNSIcon/PublicIcon.tsx create mode 100644 src/components/ResourceInstance/Connectivity/CustomDNS.tsx create mode 100644 src/components/ResourceInstance/Connectivity/CustomDNSDetails.tsx delete mode 100644 src/components/ResourceInstance/Connectivity/CustomDNSDetailsModal.tsx create mode 100644 src/components/ResourceInstance/Connectivity/CustomDNSEndPoint.tsx create mode 100644 src/components/ResourceInstance/Connectivity/ResourceCustomDNS.tsx diff --git a/pages/access/[serviceId]/[environmentId]/[resourceId]/[resourceInstanceId].js b/pages/access/[serviceId]/[environmentId]/[resourceId]/[resourceInstanceId].js index 46a2fc9d..25d99504 100644 --- a/pages/access/[serviceId]/[environmentId]/[resourceId]/[resourceInstanceId].js +++ b/pages/access/[serviceId]/[environmentId]/[resourceId]/[resourceInstanceId].js @@ -43,6 +43,7 @@ import { selectInstanceDetailsSummaryVisibility, toggleInstanceDetailsSummaryVisibility, } from "src/slices/genericSlice"; +import ResourceCustomDNS from "src/components/ResourceInstance/Connectivity/ResourceCustomDNS"; export const getServerSideProps = async () => { return { @@ -148,6 +149,25 @@ function ResourceInstance() { [resourceType] ); + const checkCustomDNSEndpoint = (resources) => { + if ( + resources.primary?.customDNSEndpoint && + resources.primary?.customDNSEndpoint.enabled === true + ) { + return true; + } + + if (Array.isArray(resources.others)) { + return resources.others.some( + (resource) => + resource?.customDNSEndpoint && + resource?.customDNSEndpoint.enabled === true + ); + } + + return false; + }; + const tabs = getTabs( resourceInstanceData?.isMetricsEnabled, resourceInstanceData?.isLogsEnabled, @@ -155,7 +175,12 @@ function ResourceInstance() { isResourceBYOA, isCliManagedResource, resourceType, - resourceInstanceData?.backupStatus?.backupPeriodInHours + resourceInstanceData?.backupStatus?.backupPeriodInHours, + checkCustomDNSEndpoint( + resourceInstanceData + ? resourceInstanceData?.connectivity?.globalEndpoints + : {} + ) ); let pageTitle = "Resource"; @@ -542,6 +567,15 @@ function ResourceInstance() { } /> )} + {currentTab === tabs.customDNS && ( + + )} + ; + textStyles?: SxProps; + iconStyles?: SxProps & { alignItems?: string; display?: string }; +}; + +export default function CustomStatusChips(props: CustomStatusChipsProps) { + const { + icon, + children, + containerStyles = {}, + textStyles = {}, + iconStyles = {}, + } = props; + const theme = useTheme(); + + return ( + + {icon && ( + + {icon} + + )} + + {children} + + + ); +} diff --git a/src/components/Icons/AlertTrianglePITR/AlertTrianglePITR.jsx b/src/components/Icons/AlertTrianglePITR/AlertTrianglePITR.jsx new file mode 100644 index 00000000..b0ac0224 --- /dev/null +++ b/src/components/Icons/AlertTrianglePITR/AlertTrianglePITR.jsx @@ -0,0 +1,26 @@ +import React from "react"; + +function AlertTrianglePITR(props) { + const { height = 21, width = 24, color = "#B54708", ...restProps } = props; + + return ( + + + + ); +} + +export default AlertTrianglePITR; diff --git a/src/components/Icons/CircleCheck/CircleCheckWithBorderIcon.jsx b/src/components/Icons/CircleCheck/CircleCheckWithBorderIcon.jsx new file mode 100644 index 00000000..0c79f96a --- /dev/null +++ b/src/components/Icons/CircleCheck/CircleCheckWithBorderIcon.jsx @@ -0,0 +1,31 @@ +function CircleCheckWithBorderIcon(props) { + const { height = 16, width = 16, ...restProps } = props; + + return ( + + + + + + + + + + + ); +} + +export default CircleCheckWithBorderIcon; diff --git a/src/components/Icons/DNSIcon/PrivateIcon.tsx b/src/components/Icons/DNSIcon/PrivateIcon.tsx new file mode 100644 index 00000000..98ab3dd1 --- /dev/null +++ b/src/components/Icons/DNSIcon/PrivateIcon.tsx @@ -0,0 +1,131 @@ +const PrivateIcon = (props: any) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); +export default PrivateIcon; diff --git a/src/components/Icons/DNSIcon/PublicIcon.tsx b/src/components/Icons/DNSIcon/PublicIcon.tsx new file mode 100644 index 00000000..1a7036d4 --- /dev/null +++ b/src/components/Icons/DNSIcon/PublicIcon.tsx @@ -0,0 +1,180 @@ +const PublicIcon = (props: any) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); +export default PublicIcon; diff --git a/src/components/ResourceInstance/Connectivity/ConnectivityCustomDNS.tsx b/src/components/ResourceInstance/Connectivity/ConnectivityCustomDNS.tsx index a5030338..d4125d38 100644 --- a/src/components/ResourceInstance/Connectivity/ConnectivityCustomDNS.tsx +++ b/src/components/ResourceInstance/Connectivity/ConnectivityCustomDNS.tsx @@ -22,7 +22,6 @@ import EditIcon from "src/components/Icons/Edit/Edit"; import DeleteIcon from "src/components/Icons/Delete/Delete"; import TextConfirmationDialog from "src/components/TextConfirmationDialog/TextConfirmationDialog"; import LoadingSpinnerSmall from "src/components/CircularProgress/CircularProgress"; -import CustomDNSDetailsModal from "./CustomDNSDetailsModal"; import StatusChip from "src/components/StatusChip/StatusChip"; import { getCustomDNSStatusStylesAndLabel } from "src/constants/statusChipStyles/customDNS"; import { useMutation } from "@tanstack/react-query"; @@ -47,6 +46,7 @@ type ResourceConnectivityEndpointProps = { status?: string; cnameTarget?: string; aRecordTarget?: string; + name?: string; }; queryData: { serviceProviderId: string; @@ -75,7 +75,6 @@ const ResourceConnectivityCustomDNS: FC = ( const [showDeleteConfirmationDialog, setShowDeleteConfirmationDialog] = useState(false); - const [showConfigurationDialog, setShowConfigurationDialog] = useState(false); const [deleteMessage, setDeleteMessage] = useState(""); const [isTextfieldDisabled, setIsTextFieldDisabled] = useState(false); const [shouldShowConfigDialog, setShouldShowConfigDialog] = useState(false); @@ -109,6 +108,8 @@ const ResourceConnectivityCustomDNS: FC = ( }, onSuccess: () => { refetchInstance(); + setShouldShowConfigDialog(true); + setIsTextFieldDisabled(true); }, }); @@ -128,6 +129,8 @@ const ResourceConnectivityCustomDNS: FC = ( }, onSuccess: () => { pollInstanceQueryToVerifyDNSRemoval(); + setShowDeleteConfirmationDialog(false); + removeCustomDNSFormik.resetForm(); }, }); @@ -209,24 +212,13 @@ const ResourceConnectivityCustomDNS: FC = ( }, onSubmit: async (values) => { if (values.confirmationText === "deleteme") { - try { - await removeCustomDNSMutation?.mutateAsync(); - setShowDeleteConfirmationDialog(false); - removeCustomDNSFormik.resetForm(); - } catch {} + removeCustomDNSMutation?.mutate(); } }, }); async function handleAddDNS(payload: AddCustomDNSToResourceInstancePayload) { - try { - await addCustomDNSMutation?.mutateAsync(payload); - setShouldShowConfigDialog(true); - setIsTextFieldDisabled(true); - - } catch (err) { - console.error(err); - } + addCustomDNSMutation?.mutate(payload); } useEffect(() => { @@ -240,7 +232,6 @@ const ResourceConnectivityCustomDNS: FC = ( useEffect(() => { if (isCustomDNSSetup && shouldShowConfigDialog) { - setShowConfigurationDialog(true); setShouldShowConfigDialog(false); } }, [isCustomDNSSetup, shouldShowConfigDialog, setShouldShowConfigDialog]); @@ -304,7 +295,7 @@ const ResourceConnectivityCustomDNS: FC = ( }} /> - + = ( /> {isTextfieldDisabled ? ( <> - { - setShowConfigurationDialog(true); - }} - > + {}}> = ( isDeleteEnable={true} /> )} - { - setShowConfigurationDialog(false); - }} - /> ); }; diff --git a/src/components/ResourceInstance/Connectivity/ConnectivityEndpoint.tsx b/src/components/ResourceInstance/Connectivity/ConnectivityEndpoint.tsx index 9a829c27..f20cea49 100644 --- a/src/components/ResourceInstance/Connectivity/ConnectivityEndpoint.tsx +++ b/src/components/ResourceInstance/Connectivity/ConnectivityEndpoint.tsx @@ -12,6 +12,7 @@ import CopyButton from "src/components/Button/CopyButton"; import Button from "src/components/Button/Button"; import AddCircleOutlineIcon from "@mui/icons-material/AddCircleOutline"; import RemoveCircleOutlineIcon from "@mui/icons-material/RemoveCircleOutline"; +import CustomDNSEndPoint from "./CustomDNSEndPoint"; const TableCell = styled(MuiTableCell)({ borderBottom: "none", }); @@ -25,6 +26,14 @@ type ResourceConnectivityEndpointProps = { containerStyles: SxProps; context: "access" | "fleet"; ResourceConnectivityCustomDNS?: any; + customDNSData?: { + enabled: boolean; + dnsName?: string; + status?: string; + cnameTarget?: string; + aRecordTarget?: string; + name?: string; + }; }; // Define the expected type for each port item @@ -44,6 +53,7 @@ const ResourceConnectivityEndpoint: FC = ( viewType, isPrimaryResource = false, ResourceConnectivityCustomDNS, + customDNSData, } = props; const [isEndpointsExpanded, setIsEndpointsExpanded] = useState(false); const toggleExpanded = () => setIsEndpointsExpanded((prev) => !prev); @@ -212,6 +222,17 @@ const ResourceConnectivityEndpoint: FC = ( + {customDNSData?.dnsName && customDNSData && ( + + + + )} ); diff --git a/src/components/ResourceInstance/Connectivity/CustomDNS.tsx b/src/components/ResourceInstance/Connectivity/CustomDNS.tsx new file mode 100644 index 00000000..b90257e1 --- /dev/null +++ b/src/components/ResourceInstance/Connectivity/CustomDNS.tsx @@ -0,0 +1,389 @@ +import { SxProps, Theme, Stack, Box } from "@mui/material"; +import { Text } from "src/components/Typography/Typography"; +import { FC, useEffect, useRef, useState } from "react"; +import FieldContainer from "src/components/FormElementsv2/FieldContainer/FieldContainer"; +import TextField from "src/components/FormElementsv2/TextField/TextField"; +import Button from "src/components/Button/Button"; +import { useFormik } from "formik"; +import { + addCustomDNSToResourceInstance, + removeCustomDNSFromResourceInstance, + getResourceInstanceDetails, +} from "src/api/resourceInstance"; + +import * as Yup from "yup"; +import FieldError from "src/components/FormElementsv2/FieldError/FieldError"; +import IconButtonSquare from "src/components/IconButtonSquare/IconButtonSquare"; +import EditIcon from "src/components/Icons/Edit/Edit"; +import DeleteIcon from "src/components/Icons/Delete/Delete"; +import TextConfirmationDialog from "src/components/TextConfirmationDialog/TextConfirmationDialog"; +import LoadingSpinnerSmall from "src/components/CircularProgress/CircularProgress"; +import { useMutation } from "@tanstack/react-query"; +import Card from "src/components/Card/Card"; +import PublicIcon from "src/components/Icons/DNSIcon/PublicIcon"; +import { AddCustomDNSToResourceInstancePayload } from "./ConnectivityCustomDNS"; +import CustomDNSDetails from "./CustomDNSDetails"; +import AlertTrianglePITR from "src/components/Icons/AlertTrianglePITR/AlertTrianglePITR"; +import CircleCheckWithBorderIcon from "src/components/Icons/CircleCheck/CircleCheckWithBorderIcon"; +import CustomStatusChips from "src/components/CustomStatusChips/CustomStatusChips"; +import PlayIcon from "src/components/Icons/Play/Play"; + +type EndpointProps = { + resourceName: string; + containerStyles?: SxProps; + resourceKey: string; + resourceId: string; + resourceHasCompute: boolean; + customDNSData?: { + enabled: boolean; + dnsName?: string; + status?: string; + cnameTarget?: string; + aRecordTarget?: string; + }; + accessQueryParams?: { + serviceProviderId: string; + serviceKey: string; + serviceAPIVersion: string; + serviceEnvironmentKey: string; + serviceModelKey: string; + productTierKey: string; + subscriptionId: string; + resourceInstanceId: string; + }; + + refetchInstance: () => void; +}; + +const CustomDNS: FC = (props) => { + const { + resourceName, + customDNSData = { enabled: false }, + accessQueryParams, + resourceKey, + resourceId, + refetchInstance, + resourceHasCompute, + } = props; + + const [showDeleteConfirmationDialog, setShowDeleteConfirmationDialog] = + useState(false); + const [deleteMessage, setDeleteMessage] = useState(""); + const [isTextfieldDisabled, setIsTextFieldDisabled] = useState(false); + const textfieldRef = useRef(); + const timeoutID = useRef(null); + const pollCount = useRef(0); + + const { dnsName } = customDNSData; + let isCustomDNSSetup = false; + if (dnsName) { + isCustomDNSSetup = true; + } + + const addCustomDNSMutation = useMutation({ + mutationFn: (payload: AddCustomDNSToResourceInstancePayload) => { + return addCustomDNSToResourceInstance( + accessQueryParams.serviceProviderId, + accessQueryParams.serviceKey, + accessQueryParams.serviceAPIVersion, + accessQueryParams.serviceEnvironmentKey, + accessQueryParams.serviceModelKey, + accessQueryParams.productTierKey, + resourceKey, + accessQueryParams.resourceInstanceId, + accessQueryParams.subscriptionId, + payload + ); + }, + onSuccess: () => { + refetchInstance(); + setIsTextFieldDisabled(true); + }, + }); + + const removeCustomDNSMutation = useMutation({ + mutationFn: () => { + return removeCustomDNSFromResourceInstance( + accessQueryParams.serviceProviderId, + accessQueryParams.serviceKey, + accessQueryParams.serviceAPIVersion, + accessQueryParams.serviceEnvironmentKey, + accessQueryParams.serviceModelKey, + accessQueryParams.productTierKey, + resourceKey, + accessQueryParams.resourceInstanceId, + accessQueryParams.subscriptionId + ); + }, + onSuccess: () => { + pollInstanceQueryToVerifyDNSRemoval(); + setShowDeleteConfirmationDialog(false); + removeCustomDNSFormik.resetForm(); + }, + }); + + function clearExistingTimeout() { + if (timeoutID.current) { + clearTimeout(timeoutID.current); + } + } + + function pollInstanceQueryToVerifyDNSRemoval() { + clearExistingTimeout(); + pollCount.current = 0; + verifyDNSRemoval(); + + function verifyDNSRemoval() { + if (pollCount.current < 5) { + pollCount.current++; + const id = setTimeout(() => { + getResourceInstanceDetails( + accessQueryParams.serviceProviderId, + accessQueryParams.serviceKey, + accessQueryParams.serviceAPIVersion, + accessQueryParams.serviceEnvironmentKey, + accessQueryParams.serviceModelKey, + accessQueryParams.productTierKey, + resourceKey, + accessQueryParams.resourceInstanceId, + accessQueryParams.subscriptionId + ) + .then((response) => { + const topologyDetails = + response.data?.detailedNetworkTopology?.[resourceId]; + //check for dnsName field in the response, absence means dns removal complete + if (!Boolean(topologyDetails?.customDNSEndpoint.dnsName)) { + refetchInstance(); + } else { + verifyDNSRemoval(); + } + }) + .catch(() => { + verifyDNSRemoval(); + }); + }, 1500); + timeoutID.current = id; + } else { + } + } + } + + useEffect(() => { + return () => { + clearExistingTimeout(); + }; + }, []); + + const customDNSFormik = useFormik({ + initialValues: { + customDNSEndpoint: dnsName ?? "", + }, + onSubmit: (values) => { + handleAddDNS({ + customDNS: values.customDNSEndpoint, + }); + }, + validationSchema: Yup.object().shape({ + customDNSEndpoint: Yup.string() + //.url("Please enter a valid URL") + .required("Target Alias is required"), + }), + enableReinitialize: true, + }); + + const removeCustomDNSFormik = useFormik({ + initialValues: { + confirmationText: "", + }, + onSubmit: async (values) => { + if (values.confirmationText === "deleteme") { + removeCustomDNSMutation?.mutate(); + } + }, + }); + + async function handleAddDNS(payload: AddCustomDNSToResourceInstancePayload) { + addCustomDNSMutation?.mutate(payload); + } + + useEffect(() => { + if (customDNSData.enabled === true && customDNSData.dnsName) { + setIsTextFieldDisabled(true); + } else if (customDNSData.enabled === true && !customDNSData.dnsName) { + setIsTextFieldDisabled(false); + } + }, [customDNSData]); + + return ( + <> + {resourceHasCompute && customDNSData?.enabled && ( + + + + + + + {resourceName} + + + + <> + + {(customDNSData?.aRecordTarget || customDNSData?.cnameTarget) && ( + + )} + + + + {isTextfieldDisabled ? ( + <> + { + setIsTextFieldDisabled(false); + //textfieldRef.current.focus(); + }} + > + + + { + setDeleteMessage( + "Are you sure you want to delete this endpoint alias?" + ); + setShowDeleteConfirmationDialog(true); + }} + > + + + + ) : ( + <> + + + )} + + + {customDNSFormik.touched.customDNSEndpoint && + customDNSFormik.errors.customDNSEndpoint} + + + {isCustomDNSSetup && ( + + ) : ( + + ) + } + containerStyles={ + customDNSData?.status === "READY" + ? { + backgroundColor: "rgba(237, 252, 242, 1)", + border: "1px solid rgba(170, 240, 196, 1)", + } + : { + backgroundColor: "rgba(254, 251, 232, 1)", + border: "1px solid rgba(254, 247, 195, 1)", + } + } + > + + {customDNSData?.status === "READY" + ? "Domain Verified" + : "Pending Verification"} + + + )} + + + {isCustomDNSSetup && ( + { + setShowDeleteConfirmationDialog(false); + removeCustomDNSFormik.resetForm(); + }} + formData={removeCustomDNSFormik} + title={`Delete Endpoint Alias`} + subtitle={deleteMessage} + message={ + "To confirm deletion, please enter deleteme, in the field below:" + } + isLoading={removeCustomDNSMutation?.isLoading} + isDeleteEnable={true} + /> + )} + + )} + + ); +}; + +export default CustomDNS; diff --git a/src/components/ResourceInstance/Connectivity/CustomDNSDetails.tsx b/src/components/ResourceInstance/Connectivity/CustomDNSDetails.tsx new file mode 100644 index 00000000..db694d30 --- /dev/null +++ b/src/components/ResourceInstance/Connectivity/CustomDNSDetails.tsx @@ -0,0 +1,175 @@ +import React from "react"; +import { Box, styled } from "@mui/material"; +import CopyButton from "src/components/Button/CopyButton"; +import { Text } from "src/components/Typography/Typography"; +import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; + +type CustomDNSDetailsProps = { + aRecordTarget?: string; + cnameTarget?: string; + domainName: string; +}; + +const RecordContainer = styled(Box)({ + display: "flex", + flexDirection: "column", + width: "100%", + padding: "24px", + border: "1px solid #EAECF0", + marginBottom: "16px", + boxShadow: "0px 1px 2px 0px rgba(16, 24, 40, 0.05)", +}); + +const RecordRowContainer = styled(Box)({ + display: "flex", + flexDirection: "row", + alignItems: "center", + width: "100%", + marginBottom: "16px", +}); +const RecordColumn = styled(Box)<{ hasBorder?: boolean }>(({ hasBorder }) => ({ + display: "flex", + alignItems: "center", + border: hasBorder ? "1px solid #EAECF0" : "none", + borderRadius: "8px", + flex: 1, + minHeight: "40px", + backgroundColor: "#fff", + overflow: "hidden", + boxShadow: hasBorder ? "0px 1px 2px 0px rgba(16, 24, 40, 0.05)" : "none", +})); + +const CustomDNSDetails: React.FC = ({ + aRecordTarget, + cnameTarget, + domainName, +}) => { + const records = []; + if (aRecordTarget) { + records.push({ + recordLabel: "A", + domainValue: domainName, + recordValue: aRecordTarget, + }); + } + + if (cnameTarget) { + records.push({ + recordLabel: "CNAME", + domainValue: domainName, + recordValue: cnameTarget, + }); + } + + return ( + + {records.map((record, index) => ( + + + + + Record Name + + + + + + + Record Value + + + + + + + + + + {record.recordLabel} + + + + + + {record.domainValue} + + + + + + + + + + + + + + + + {record.recordValue} + + + + + + + + + + ))} + + ); +}; + +export default CustomDNSDetails; diff --git a/src/components/ResourceInstance/Connectivity/CustomDNSDetailsModal.tsx b/src/components/ResourceInstance/Connectivity/CustomDNSDetailsModal.tsx deleted file mode 100644 index 0d14261c..00000000 --- a/src/components/ResourceInstance/Connectivity/CustomDNSDetailsModal.tsx +++ /dev/null @@ -1,98 +0,0 @@ -import { - Box, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - Stack, -} from "@mui/material"; -import { FC } from "react"; -import Accordian from "src/components/Accordian/Accordian"; -import AccordionKeyValueCopyTable from "src/components/AccordionKeyValueCopyTable/AccordionKeyValueCopyTable"; -import Button from "src/components/Button/Button"; -import Divider from "src/components/Divider/Divider"; -import InfoIcon from "src/components/Icons/Info/Info"; -import { Text } from "src/components/Typography/Typography"; - -type CustomDNSDetailsModalProps = { - open: boolean; - handleClose: () => void; - aRecordTarget?: string; - cnameTarget?: string; - domainName: string; -}; - -const CustomDNSDetailsModal: FC = (props) => { - const { open, handleClose, aRecordTarget, cnameTarget, domainName } = props; - - const rows = [ - { - label: "Domain Name", - value: domainName, - }, - { - label: cnameTarget ? "Target Endpoint" : "Target IP", - value: cnameTarget ? cnameTarget : aRecordTarget, - }, - ]; - - const title = cnameTarget ? "CNAME" : "A Record"; - - return ( - - - - - - - - Alias Configuration - - - Configure your custom DNS settings - - - - - - - - - - - - - - - - ); -}; - -export default CustomDNSDetailsModal; diff --git a/src/components/ResourceInstance/Connectivity/CustomDNSEndPoint.tsx b/src/components/ResourceInstance/Connectivity/CustomDNSEndPoint.tsx new file mode 100644 index 00000000..e4bd258a --- /dev/null +++ b/src/components/ResourceInstance/Connectivity/CustomDNSEndPoint.tsx @@ -0,0 +1,91 @@ +import { Box, styled, SxProps, Theme } from "@mui/material"; +import Image from "next/image"; +import Table from "@mui/material/Table"; +import TableBody from "@mui/material/TableBody"; +import TableRow from "@mui/material/TableRow"; +import MuiTableCell from "@mui/material/TableCell"; +import { Text } from "src/components/Typography/Typography"; +import resourceEndpointIcon from "../../../../public/assets/images/dashboard/resource-instance-nodes/resource-endpoint.svg"; +import CopyButton from "src/components/Button/CopyButton"; +const TableCell = styled(MuiTableCell)({ + borderBottom: "none", +}); +type CustomDNSEndPointProps = { + isPrimaryResource: boolean; + endpointURL: string; + containerStyles?: SxProps; + endpointName: string; +}; + +const CustomDNSEndPoint: React.FC = ({ + isPrimaryResource, + endpointURL, + containerStyles, + endpointName, +}) => { + return ( + + + + + + + + + + {endpointName} + + + + + {endpointURL} + + + + + + +
+
+ ); +}; + +export default CustomDNSEndPoint; diff --git a/src/components/ResourceInstance/Connectivity/ResourceCustomDNS.tsx b/src/components/ResourceInstance/Connectivity/ResourceCustomDNS.tsx new file mode 100644 index 00000000..3c006109 --- /dev/null +++ b/src/components/ResourceInstance/Connectivity/ResourceCustomDNS.tsx @@ -0,0 +1,130 @@ +import { Box } from "@mui/material"; +import { useMemo } from "react"; +import PropertyTable from "./PropertyTable"; +import CustomDNS from "./CustomDNS"; + +function ResourceCustomDNS(props) { + const { + globalEndpoints, + context, + addCustomDNSMutation, + removeCustomDNSMutation, + accessQueryParams, + refetchInstance, + } = props; + + const primaryResourceName = globalEndpoints?.primary?.resourceName; + const primaryResourceEndpoint = globalEndpoints?.primary?.endpoint; + + const [otherResourceFilteredEndpoints] = useMemo(() => { + const otherEndpoints = globalEndpoints?.others; + + const otherResourceFilteredEndpoints = []; + + otherEndpoints?.forEach((endpointData) => { + const { resourceName, endpoint } = endpointData; + if (resourceName && endpoint) { + // filter out omnistrate observability + if (resourceName === "Omnistrate Observability") { + return; + } + otherResourceFilteredEndpoints.push(endpointData); + } + }); + return [otherResourceFilteredEndpoints]; + }, [globalEndpoints]); + + const rows = useMemo(() => { + let sectionLabel = "Resource"; + + if (context === "inventory") { + sectionLabel = "Service Component"; + } + + const res = []; + + if (primaryResourceName || otherResourceFilteredEndpoints?.length > 0) { + const customDNSEndpointName = + globalEndpoints?.primary?.customDNSEndpoint?.name ?? ""; + if ( + globalEndpoints?.primary?.resourceHasCompute && + globalEndpoints?.primary?.customDNSEndpoint?.enabled + ) { + res.push({ + label: primaryResourceName, + description: `The global endpoint of the ${sectionLabel.toLowerCase()}`, + valueType: "custom", + value: ( + <> + {primaryResourceName && ( + + )} + + ), + }); + } + } + + if (otherResourceFilteredEndpoints?.length > 0) { + otherResourceFilteredEndpoints.forEach( + ({ + resourceName, + resourceKey, + resourceId, + resourceHasCompute, + customDNSEndpoint, + }) => { + const customDNSEndpointName = customDNSEndpoint?.name ?? ""; + if (resourceHasCompute && customDNSEndpoint?.enabled) { + res.push({ + label: resourceName, + description: `The global endpoint of the ${sectionLabel.toLowerCase()}`, + valueType: "custom", + value: ( + + ), + }); + } + } + ); + } + + return res; + }, [ + context, + primaryResourceName, + primaryResourceEndpoint, + otherResourceFilteredEndpoints, + globalEndpoints?.primary?.customDNSEndpoint, + addCustomDNSMutation, + removeCustomDNSMutation, + ]); + + return ( + rows.length > 0 && ( + + + + ) + ); +} + +export default ResourceCustomDNS;