diff --git a/frontend/public/locales/en-GB/routes.json b/frontend/public/locales/en-GB/routes.json index c88baa096a0..47b86d3f27e 100644 --- a/frontend/public/locales/en-GB/routes.json +++ b/frontend/public/locales/en-GB/routes.json @@ -6,6 +6,7 @@ "api_keys": "API Keys", "my_settings": "My Settings", "overview_metrics": "Overview Metrics", + "custom_domain_settings": "Custom Domain Settings", "dbcall_metrics": "Database Calls", "external_metrics": "External Calls", "pipeline": "Pipeline", diff --git a/frontend/public/locales/en-GB/titles.json b/frontend/public/locales/en-GB/titles.json index 6a458ab23e9..bdee0edae85 100644 --- a/frontend/public/locales/en-GB/titles.json +++ b/frontend/public/locales/en-GB/titles.json @@ -27,6 +27,7 @@ "ORG_SETTINGS": "SigNoz | Organization Settings", "INGESTION_SETTINGS": "SigNoz | Ingestion Settings", "API_KEYS": "SigNoz | API Keys", + "CUSTOM_DOMAIN_SETTINGS": "SigNoz | Custom Domain Settings", "SOMETHING_WENT_WRONG": "SigNoz | Something Went Wrong", "UN_AUTHORIZED": "SigNoz | Unauthorized", "NOT_FOUND": "SigNoz | Page Not Found", diff --git a/frontend/public/locales/en/routes.json b/frontend/public/locales/en/routes.json index c88baa096a0..47b86d3f27e 100644 --- a/frontend/public/locales/en/routes.json +++ b/frontend/public/locales/en/routes.json @@ -6,6 +6,7 @@ "api_keys": "API Keys", "my_settings": "My Settings", "overview_metrics": "Overview Metrics", + "custom_domain_settings": "Custom Domain Settings", "dbcall_metrics": "Database Calls", "external_metrics": "External Calls", "pipeline": "Pipeline", diff --git a/frontend/public/locales/en/titles.json b/frontend/public/locales/en/titles.json index 90dde56b320..e2adcac3515 100644 --- a/frontend/public/locales/en/titles.json +++ b/frontend/public/locales/en/titles.json @@ -33,6 +33,7 @@ "ORG_SETTINGS": "SigNoz | Organization Settings", "INGESTION_SETTINGS": "SigNoz | Ingestion Settings", "API_KEYS": "SigNoz | API Keys", + "CUSTOM_DOMAIN_SETTINGS": "SigNoz | Custom Domain Settings", "SOMETHING_WENT_WRONG": "SigNoz | Something Went Wrong", "UN_AUTHORIZED": "SigNoz | Unauthorized", "NOT_FOUND": "SigNoz | Page Not Found", diff --git a/frontend/src/AppRoutes/pageComponents.ts b/frontend/src/AppRoutes/pageComponents.ts index fb63e865cbc..0857ea46640 100644 --- a/frontend/src/AppRoutes/pageComponents.ts +++ b/frontend/src/AppRoutes/pageComponents.ts @@ -145,6 +145,11 @@ export const MySettings = Loadable( () => import(/* webpackChunkName: "All MySettings" */ 'pages/MySettings'), ); +export const CustomDomainSettings = Loadable( + () => + import(/* webpackChunkName: "Custom Domain Settings" */ 'pages/Settings'), +); + export const Logs = Loadable( () => import(/* webpackChunkName: "Logs" */ 'pages/LogsModulePage'), ); diff --git a/frontend/src/AppRoutes/routes.ts b/frontend/src/AppRoutes/routes.ts index 1291e32cb1e..0b4899c4a1a 100644 --- a/frontend/src/AppRoutes/routes.ts +++ b/frontend/src/AppRoutes/routes.ts @@ -10,6 +10,7 @@ import { BillingPage, CreateAlertChannelAlerts, CreateNewAlerts, + CustomDomainSettings, DashboardPage, DashboardWidget, EditAlertChannelsAlerts, @@ -288,6 +289,13 @@ const routes: AppRoutes[] = [ isPrivate: true, key: 'MY_SETTINGS', }, + { + path: ROUTES.CUSTOM_DOMAIN_SETTINGS, + exact: true, + component: CustomDomainSettings, + isPrivate: true, + key: 'CUSTOM_DOMAIN_SETTINGS', + }, { path: ROUTES.LOGS, exact: true, diff --git a/frontend/src/api/customDomain/getDeploymentsData.ts b/frontend/src/api/customDomain/getDeploymentsData.ts new file mode 100644 index 00000000000..5af62309bfc --- /dev/null +++ b/frontend/src/api/customDomain/getDeploymentsData.ts @@ -0,0 +1,7 @@ +import { GatewayApiV2Instance as axios } from 'api'; +import { AxiosResponse } from 'axios'; +import { DeploymentsDataProps } from 'types/api/customDomain/types'; + +export const getDeploymentsData = (): Promise< + AxiosResponse +> => axios.get(`/deployments/me`); diff --git a/frontend/src/api/customDomain/updateSubDomain.ts b/frontend/src/api/customDomain/updateSubDomain.ts new file mode 100644 index 00000000000..8529cec7efd --- /dev/null +++ b/frontend/src/api/customDomain/updateSubDomain.ts @@ -0,0 +1,16 @@ +import { GatewayApiV2Instance as axios } from 'api'; +import { AxiosError } from 'axios'; +import { SuccessResponse } from 'types/api'; +import { + PayloadProps, + UpdateCustomDomainProps, +} from 'types/api/customDomain/types'; + +const updateSubDomainAPI = async ( + props: UpdateCustomDomainProps, +): Promise | AxiosError> => + axios.put(`/deployments/me/host`, { + ...props.data, + }); + +export default updateSubDomainAPI; diff --git a/frontend/src/components/CustomTimePicker/TimezonePicker.tsx b/frontend/src/components/CustomTimePicker/TimezonePicker.tsx index 0259e51087e..63d4502558d 100644 --- a/frontend/src/components/CustomTimePicker/TimezonePicker.tsx +++ b/frontend/src/components/CustomTimePicker/TimezonePicker.tsx @@ -127,7 +127,6 @@ function TimezonePicker({ setIsOpen, isOpenedFromFooter, }: TimezonePickerProps): JSX.Element { - console.log({ isOpenedFromFooter }); const [searchTerm, setSearchTerm] = useState(''); const { timezone, updateTimezone } = useTimezone(); const [selectedTimezone, setSelectedTimezone] = useState( diff --git a/frontend/src/constants/routes.ts b/frontend/src/constants/routes.ts index e757557d028..b31accd613a 100644 --- a/frontend/src/constants/routes.ts +++ b/frontend/src/constants/routes.ts @@ -34,6 +34,7 @@ const ROUTES = { MY_SETTINGS: '/my-settings', SETTINGS: '/settings', ORG_SETTINGS: '/settings/org-settings', + CUSTOM_DOMAIN_SETTINGS: '/settings/custom-domain-settings', API_KEYS: '/settings/api-keys', INGESTION_SETTINGS: '/settings/ingestion-settings', SOMETHING_WENT_WRONG: '/something-went-wrong', diff --git a/frontend/src/container/CustomDomainSettings/CustomDomainSettings.styles.scss b/frontend/src/container/CustomDomainSettings/CustomDomainSettings.styles.scss new file mode 100644 index 00000000000..7b4d507eb37 --- /dev/null +++ b/frontend/src/container/CustomDomainSettings/CustomDomainSettings.styles.scss @@ -0,0 +1,262 @@ +.custom-domain-settings-container { + margin-top: 24px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: 24px; + width: 100%; + + .custom-domain-settings-content { + width: calc(100% - 30px); + max-width: 736px; + + .title { + color: var(--bg-vanilla-100); + font-size: var(--font-size-lg); + font-style: normal; + font-weight: var(--font-weight-normal); + line-height: 28px; /* 155.556% */ + letter-spacing: -0.09px; + } + + .subtitle { + color: var(--bg-vanilla-400); + font-size: var(--font-size-sm); + font-style: normal; + font-weight: var(--font-weight-normal); + line-height: 20px; /* 142.857% */ + letter-spacing: -0.07px; + } + } + + .custom-domain-settings-card { + border-radius: 4px; + border: 1px solid var(--bg-slate-400); + background: var(--bg-ink-400); + + .ant-card-body { + padding: 12px; + + display: flex; + flex-direction: column; + + .custom-domain-settings-content-header { + color: var(--bg-vanilla-100); + font-size: var(--font-size-sm); + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: 20px; /* 142.857% */ + letter-spacing: -0.07px; + } + + .custom-domain-settings-content-body { + margin-top: 12px; + display: flex; + gap: 12px; + + align-items: flex-end; + justify-content: space-between; + + .custom-domain-url-edit-btn { + .periscope-btn { + border-radius: 2px; + border: 1px solid var(--Slate-200, #2c3140); + background: var(--Ink-200, #23262e); + } + } + } + + .custom-domain-urls { + display: flex; + flex-direction: column; + flex: 1; + } + + .custom-domain-url { + display: flex; + align-items: center; + gap: 8px; + cursor: pointer; + + line-height: 24px; + padding: 4px 0; + } + + .custom-domain-update-status { + margin-top: 12px; + + color: var(--bg-robin-400); + font-size: 13px; + font-style: normal; + font-weight: var(--font-weight-medium); + line-height: 20px; + letter-spacing: -0.07px; + border-radius: 4px; + border: 1px solid rgba(78, 116, 248, 0.1); + background: rgba(78, 116, 248, 0.1); + } + } + } +} + +.custom-domain-settings-modal { + .ant-modal-content { + border-radius: 4px; + border: 1px solid var(--bg-slate-500); + background: var(--bg-ink-400); + box-shadow: 0px -4px 16px 2px rgba(0, 0, 0, 0.2); + padding: 0; + + .ant-modal-header { + background: none; + border-bottom: 1px solid var(--bg-slate-500); + padding: 16px; + margin-bottom: 0; + } + + .ant-modal-close-x { + font-size: 12px; + } + + .ant-modal-body { + padding: 12px 16px; + + .custom-domain-settings-modal-body { + margin-bottom: 48px; + + font-size: 13px; + font-style: normal; + font-weight: var(--font-weight-normal); + line-height: 20px; /* 142.857% */ + letter-spacing: -0.07px; + } + } + + .custom-domain-settings-modal-error { + display: flex; + flex-direction: column; + gap: 24px; + + .update-limit-reached-error { + display: flex; + padding: 20px 24px 24px 24px; + flex-direction: column; + align-items: center; + gap: 24px; + align-self: stretch; + + border-radius: 4px; + border: 1px solid rgba(255, 205, 86, 0.2); + background: rgba(255, 205, 86, 0.1); + + color: var(--bg-amber-400); + font-size: 13px; + font-style: normal; + line-height: 20px; /* 142.857% */ + } + + .ant-alert-message::first-letter { + text-transform: capitalize; + } + } + + .custom-domain-settings-modal-footer { + padding: 16px 0; + margin-top: 0; + + display: flex; + justify-content: flex-end; + + .apply-changes-btn { + width: 100%; + } + + .facing-issue-button { + width: 100%; + + .periscope-btn { + width: 100%; + + border-radius: 2px; + background: var(--bg-robin-500); + border: none; + + color: var(--bg-vanilla-100); + line-height: 20px; + + .ant-btn-icon { + display: none; + } + + &:hover { + background: var(--bg-robin-500) !important; + border: none !important; + color: var(--bg-vanilla-100) !important; + line-height: 20px !important; + } + } + } + } + } +} + +.lightMode { + .custom-domain-settings-container { + .custom-domain-settings-content { + .title { + color: var(--bg-ink-400); + } + + .subtitle { + color: var(--bg-vanilla-400); + } + } + + .custom-domain-settings-card { + border: 1px solid var(--bg-vanilla-300); + background: var(--bg-vanilla-100); + + .ant-card-body { + .custom-domain-settings-content-header { + color: var(--bg-ink-100); + } + + .custom-domain-update-status { + color: var(--bg-robin-400); + border: 1px solid rgba(78, 116, 248, 0.1); + background: rgba(78, 116, 248, 0.1); + } + + .custom-domain-url-edit-btn { + .periscope-btn { + border: 1px solid var(--bg-vanilla-300); + background: var(--bg-vanilla-100); + box-shadow: none; + } + } + } + } + } + + .custom-domain-settings-modal { + .ant-modal-content { + border: 1px solid var(--bg-vanilla-300); + background: var(--bg-vanilla-100); + box-shadow: 0px -4px 16px 2px rgba(0, 0, 0, 0.2); + + .ant-modal-header { + border-bottom: 1px solid var(--bg-vanilla-300); + } + + .custom-domain-settings-modal-error { + .update-limit-reached-error { + border: 1px solid rgba(255, 205, 86, 0.2); + background: rgba(255, 205, 86, 0.1); + + color: var(--bg-amber-500); + } + } + } + } +} diff --git a/frontend/src/container/CustomDomainSettings/CustomDomainSettings.tsx b/frontend/src/container/CustomDomainSettings/CustomDomainSettings.tsx new file mode 100644 index 00000000000..1ee424b5aff --- /dev/null +++ b/frontend/src/container/CustomDomainSettings/CustomDomainSettings.tsx @@ -0,0 +1,300 @@ +/* eslint-disable jsx-a11y/no-static-element-interactions */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +import './CustomDomainSettings.styles.scss'; + +import { Color } from '@signozhq/design-tokens'; +import { + Alert, + Button, + Card, + Form, + Input, + Modal, + Skeleton, + Tag, + Typography, +} from 'antd'; +import updateSubDomainAPI from 'api/customDomain/updateSubDomain'; +import { AxiosError } from 'axios'; +import LaunchChatSupport from 'components/LaunchChatSupport/LaunchChatSupport'; +import { useGetDeploymentsData } from 'hooks/CustomDomain/useGetDeploymentsData'; +import { useNotifications } from 'hooks/useNotifications'; +import { InfoIcon, Link2, Pencil } from 'lucide-react'; +import { useAppContext } from 'providers/App/App'; +import { useEffect, useState } from 'react'; +import { useMutation } from 'react-query'; +import { useCopyToClipboard } from 'react-use'; +import { HostsProps } from 'types/api/customDomain/types'; + +interface CustomDomainSettingsProps { + subdomain: string; +} + +export default function CustomDomainSettings(): JSX.Element { + const { org } = useAppContext(); + const { notifications } = useNotifications(); + const [isEditModalOpen, setIsEditModalOpen] = useState(false); + const [isPollingEnabled, setIsPollingEnabled] = useState(false); + const [hosts, setHosts] = useState(null); + + const [updateDomainError, setUpdateDomainError] = useState( + null, + ); + + const [, setCopyUrl] = useCopyToClipboard(); + + const [ + customDomainDetails, + setCustomDomainDetails, + ] = useState(); + + const [editForm] = Form.useForm(); + + const handleModalClose = (): void => { + setIsEditModalOpen(false); + editForm.resetFields(); + setUpdateDomainError(null); + }; + + const { + data: deploymentsData, + isLoading: isLoadingDeploymentsData, + isFetching: isFetchingDeploymentsData, + refetch: refetchDeploymentsData, + } = useGetDeploymentsData(); + + const { + mutate: updateSubDomain, + isLoading: isLoadingUpdateCustomDomain, + } = useMutation(updateSubDomainAPI, { + onSuccess: () => { + setIsPollingEnabled(true); + refetchDeploymentsData(); + setIsEditModalOpen(false); + }, + onError: (error: AxiosError) => { + setUpdateDomainError(error); + setIsPollingEnabled(false); + }, + }); + + useEffect(() => { + if (deploymentsData?.data?.status === 'success') { + setHosts(deploymentsData.data.data.hosts); + + const activeCustomDomain = deploymentsData.data.data.hosts.find( + (host) => !host.is_default, + ); + + if (activeCustomDomain) { + setCustomDomainDetails({ + subdomain: activeCustomDomain?.name || '', + }); + } + } + + if (deploymentsData?.data?.data?.state !== 'HEALTHY' && isPollingEnabled) { + setTimeout(() => { + refetchDeploymentsData(); + }, 3000); + } + + if (deploymentsData?.data?.data.state === 'HEALTHY') { + setIsPollingEnabled(false); + } + }, [deploymentsData, refetchDeploymentsData, isPollingEnabled]); + + const onUpdateCustomDomainSettings = (): void => { + editForm + .validateFields() + .then((values) => { + if (values.subdomain) { + updateSubDomain({ + data: { + name: values.subdomain, + }, + }); + + setCustomDomainDetails({ + subdomain: values.subdomain, + }); + } + }) + .catch((errorInfo) => { + console.error('error info', errorInfo); + }); + }; + + const onCopyUrlHandler = (host: string): void => { + const url = `${host}.${deploymentsData?.data.data.cluster.region.dns}`; + + setCopyUrl(url); + notifications.success({ + message: 'Copied to clipboard', + }); + }; + + return ( +
+
+
+ + Custom Domain Settings + + + Personalize your workspace domain effortlessly. + +
+
+ +
+ {!isLoadingDeploymentsData && ( + +
+ Team {org?.[0]?.name} Information +
+ +
+
+ {hosts?.map((host) => ( +
onCopyUrlHandler(host.name)} + > + {host.name}. + {deploymentsData?.data.data.cluster.region.dns} + {host.is_default && Default} +
+ ))} +
+ +
+ +
+
+ + {isPollingEnabled && ( + } + /> + )} +
+ )} + + {isLoadingDeploymentsData && ( + + + + )} +
+ + {/* Update Custom Domain Modal */} + +
+ {updateDomainError?.status !== 409 && ( + <> +
+ Enter your preferred subdomain to create a unique URL for your team. + Need help? Contact support. +
+ + + } + placeholder="Enter Domain" + onChange={(): void => setUpdateDomainError(null)} + addonAfter={deploymentsData?.data.data.cluster.region.dns} + autoFocus + /> + + + )} + + {updateDomainError && ( +
+ {updateDomainError.status === 409 ? ( + + ) : ( + + {(updateDomainError.response?.data as { error: string })?.error} + + )} +
+ )} + + {updateDomainError?.status !== 409 && ( +
+ +
+ )} + + {updateDomainError?.status === 409 && ( +
+ +
+ )} +
+
+
+ ); +} diff --git a/frontend/src/container/CustomDomainSettings/index.tsx b/frontend/src/container/CustomDomainSettings/index.tsx new file mode 100644 index 00000000000..dd1b482248f --- /dev/null +++ b/frontend/src/container/CustomDomainSettings/index.tsx @@ -0,0 +1,3 @@ +import CustomDomainSettings from './CustomDomainSettings'; + +export default CustomDomainSettings; diff --git a/frontend/src/container/PlannedDowntime/PlannedDowntimeutils.ts b/frontend/src/container/PlannedDowntime/PlannedDowntimeutils.ts index feba0cb13ec..953c371887b 100644 --- a/frontend/src/container/PlannedDowntime/PlannedDowntimeutils.ts +++ b/frontend/src/container/PlannedDowntime/PlannedDowntimeutils.ts @@ -253,7 +253,7 @@ export function formatWithTimezone( ): string { const parsedDate = typeof dateValue === 'string' ? dateValue : dateValue?.format(); - console.log('dateValue', parsedDate, 'timezone', timezone); + // Get the target timezone offset const targetOffset = convertUtcOffsetToTimezoneOffset( dayjs(dateValue).tz(timezone).utcOffset(), diff --git a/frontend/src/container/TopNav/Breadcrumbs/index.tsx b/frontend/src/container/TopNav/Breadcrumbs/index.tsx index 92f9bd37bba..f234d7335f0 100644 --- a/frontend/src/container/TopNav/Breadcrumbs/index.tsx +++ b/frontend/src/container/TopNav/Breadcrumbs/index.tsx @@ -17,6 +17,7 @@ const breadcrumbNameMap: Record = { [ROUTES.ORG_SETTINGS]: 'Organization Settings', [ROUTES.INGESTION_SETTINGS]: 'Ingestion Settings', [ROUTES.MY_SETTINGS]: 'My Settings', + [ROUTES.CUSTOM_DOMAIN_SETTINGS]: 'Custom Domain Settings', [ROUTES.ERROR_DETAIL]: 'Exceptions', [ROUTES.LIST_ALL_ALERT]: 'Alerts', [ROUTES.ALL_DASHBOARD]: 'Dashboard', diff --git a/frontend/src/container/TopNav/DateTimeSelectionV2/config.ts b/frontend/src/container/TopNav/DateTimeSelectionV2/config.ts index a84e1b2c7ef..8fdd1e8c53f 100644 --- a/frontend/src/container/TopNav/DateTimeSelectionV2/config.ts +++ b/frontend/src/container/TopNav/DateTimeSelectionV2/config.ts @@ -190,6 +190,7 @@ export const routesToSkip = [ ROUTES.ALL_DASHBOARD, ROUTES.ORG_SETTINGS, ROUTES.INGESTION_SETTINGS, + ROUTES.CUSTOM_DOMAIN_SETTINGS, ROUTES.API_KEYS, ROUTES.ERROR_DETAIL, ROUTES.LOGS_PIPELINES, diff --git a/frontend/src/hooks/CustomDomain/useGetDeploymentsData.ts b/frontend/src/hooks/CustomDomain/useGetDeploymentsData.ts new file mode 100644 index 00000000000..287043b3474 --- /dev/null +++ b/frontend/src/hooks/CustomDomain/useGetDeploymentsData.ts @@ -0,0 +1,13 @@ +import { getDeploymentsData } from 'api/customDomain/getDeploymentsData'; +import { AxiosError, AxiosResponse } from 'axios'; +import { useQuery, UseQueryResult } from 'react-query'; +import { DeploymentsDataProps } from 'types/api/customDomain/types'; + +export const useGetDeploymentsData = (): UseQueryResult< + AxiosResponse, + AxiosError +> => + useQuery, AxiosError>({ + queryKey: ['getDeploymentsData'], + queryFn: () => getDeploymentsData(), + }); diff --git a/frontend/src/pages/Settings/config.tsx b/frontend/src/pages/Settings/config.tsx index 94b06a55471..d7ecc8e79d6 100644 --- a/frontend/src/pages/Settings/config.tsx +++ b/frontend/src/pages/Settings/config.tsx @@ -2,13 +2,21 @@ import { RouteTabProps } from 'components/RouteTab/types'; import ROUTES from 'constants/routes'; import AlertChannels from 'container/AllAlertChannels'; import APIKeys from 'container/APIKeys/APIKeys'; +import CustomDomainSettings from 'container/CustomDomainSettings'; import GeneralSettings from 'container/GeneralSettings'; import GeneralSettingsCloud from 'container/GeneralSettingsCloud'; import IngestionSettings from 'container/IngestionSettings/IngestionSettings'; import MultiIngestionSettings from 'container/IngestionSettings/MultiIngestionSettings'; import OrganizationSettings from 'container/OrganizationSettings'; import { TFunction } from 'i18next'; -import { Backpack, BellDot, Building, Cpu, KeySquare } from 'lucide-react'; +import { + Backpack, + BellDot, + Building, + Cpu, + Globe, + KeySquare, +} from 'lucide-react'; export const organizationSettings = (t: TFunction): RouteTabProps['routes'] => [ { @@ -102,3 +110,16 @@ export const apiKeys = (t: TFunction): RouteTabProps['routes'] => [ key: ROUTES.API_KEYS, }, ]; + +export const customDomainSettings = (t: TFunction): RouteTabProps['routes'] => [ + { + Component: CustomDomainSettings, + name: ( +
+ {t('routes:custom_domain_settings').toString()} +
+ ), + route: ROUTES.CUSTOM_DOMAIN_SETTINGS, + key: ROUTES.CUSTOM_DOMAIN_SETTINGS, + }, +]; diff --git a/frontend/src/pages/Settings/utils.ts b/frontend/src/pages/Settings/utils.ts index d789e197d0f..38b02fba473 100644 --- a/frontend/src/pages/Settings/utils.ts +++ b/frontend/src/pages/Settings/utils.ts @@ -6,6 +6,7 @@ import { isCloudUser, isEECloudUser } from 'utils/app'; import { alertChannels, apiKeys, + customDomainSettings, generalSettings, ingestionSettings, multiIngestionSettings, @@ -20,28 +21,35 @@ export const getRoutes = ( ): RouteTabProps['routes'] => { const settings = []; + const isCloudAccount = isCloudUser(); + const isEECloudAccount = isEECloudUser(); + + const isAdmin = userRole === USER_ROLES.ADMIN; + const isEditor = userRole === USER_ROLES.EDITOR; + settings.push(...generalSettings(t)); if (isCurrentOrgSettings) { settings.push(...organizationSettings(t)); } - if ( - isGatewayEnabled && - (userRole === USER_ROLES.ADMIN || userRole === USER_ROLES.EDITOR) - ) { + if (isGatewayEnabled && (isAdmin || isEditor)) { settings.push(...multiIngestionSettings(t)); } - if (isCloudUser() && !isGatewayEnabled) { + if (isCloudAccount && !isGatewayEnabled) { settings.push(...ingestionSettings(t)); } settings.push(...alertChannels(t)); - if ((isCloudUser() || isEECloudUser()) && userRole === USER_ROLES.ADMIN) { + if ((isCloudAccount || isEECloudAccount) && isAdmin) { settings.push(...apiKeys(t)); } + if (isCloudAccount && isAdmin) { + settings.push(...customDomainSettings(t)); + } + return settings; }; diff --git a/frontend/src/types/api/customDomain/types.ts b/frontend/src/types/api/customDomain/types.ts new file mode 100644 index 00000000000..268f4f4f6b1 --- /dev/null +++ b/frontend/src/types/api/customDomain/types.ts @@ -0,0 +1,53 @@ +export interface HostsProps { + name: string; + is_default: boolean; +} + +export interface RegionProps { + id: string; + name: string; + category: string; + dns: string; + created_at: string; + updated_at: string; +} + +export interface ClusterProps { + id: string; + name: string; + cloud_account_id: string; + cloud_region: string; + address: string; + region: RegionProps; +} + +export interface DeploymentData { + id: string; + name: string; + email: string; + state: string; + tier: string; + user: string; + password: string; + created_at: string; + updated_at: string; + cluster_id: string; + hosts: HostsProps[]; + cluster: ClusterProps; +} + +export interface DeploymentsDataProps { + status: string; + data: DeploymentData; +} + +export type PayloadProps = { + status: string; + data: string; +}; + +export interface UpdateCustomDomainProps { + data: { + name: string; + }; +} diff --git a/frontend/src/utils/permission/index.ts b/frontend/src/utils/permission/index.ts index c546a55755c..b1f26c4abd7 100644 --- a/frontend/src/utils/permission/index.ts +++ b/frontend/src/utils/permission/index.ts @@ -100,6 +100,7 @@ export const routePermission: Record = { LOGS_SAVE_VIEWS: ['ADMIN', 'EDITOR', 'VIEWER'], TRACES_SAVE_VIEWS: ['ADMIN', 'EDITOR', 'VIEWER'], API_KEYS: ['ADMIN'], + CUSTOM_DOMAIN_SETTINGS: ['ADMIN'], LOGS_BASE: [], OLD_LOGS_EXPLORER: ['ADMIN', 'EDITOR', 'VIEWER'], SHORTCUTS: ['ADMIN', 'EDITOR', 'VIEWER'],