diff --git a/packages/manager/modules/metrics-to-customer/src/MetricsToCustomer.module.tsx b/packages/manager/modules/metrics-to-customer/src/MetricsToCustomer.module.tsx index bd6b9402cc79..87f2fe9d4615 100644 --- a/packages/manager/modules/metrics-to-customer/src/MetricsToCustomer.module.tsx +++ b/packages/manager/modules/metrics-to-customer/src/MetricsToCustomer.module.tsx @@ -11,7 +11,7 @@ import getMetricsToCustomerRoutes from '@/routes/routes'; import { NAMESPACES } from '@/MetricsToCustomer.translations'; import { DashboardProvider, MetricsToCustomerProvider } from '@/contexts'; -import { useIamResourceLocation } from '@/data/hooks'; +import { useIamRegionsAndCapabilitiesMetrics } from '@/data/hooks'; import { Spinner, SPINNER_SIZE } from '@ovhcloud/ods-react'; export function MetricsToCustomerModule( @@ -28,21 +28,14 @@ export function MetricsToCustomerModule( enableConfigurationManagement, } = moduleProps; + const { + isPending, + isSuccess, + regions, + capabilitiesMetrics, + } = useIamRegionsAndCapabilitiesMetrics(resourceURN); - const { - isLoading, - isSuccess, - data, - } = useIamResourceLocation(resourceURN); - - const regions = [ - { - code: data?.name ?? "", - label: data?.location ?? "" - } - ]; - - if (isLoading) { + if (isPending) { return } @@ -51,6 +44,7 @@ export function MetricsToCustomerModule( resourceName, resourceURN, regions, + capabilitiesMetrics, }; const context = enableConfigurationManagement @@ -64,7 +58,7 @@ export function MetricsToCustomerModule( }; return ( - {t('loading_metrics_module')}}> + {t('loading_metrics_module')}}> { isSuccess && ( diff --git a/packages/manager/modules/metrics-to-customer/src/__mocks__/metrics-for-manager/metrics-for-manager.adapter.ts b/packages/manager/modules/metrics-to-customer/src/__mocks__/metrics-for-manager/metrics-for-manager.adapter.ts index 3c6de77d7c4d..4fb93ff55610 100644 --- a/packages/manager/modules/metrics-to-customer/src/__mocks__/metrics-for-manager/metrics-for-manager.adapter.ts +++ b/packages/manager/modules/metrics-to-customer/src/__mocks__/metrics-for-manager/metrics-for-manager.adapter.ts @@ -12,11 +12,12 @@ import { MetricData } from '@/types/observability.type'; export const fetchChartData = async ( params: ObservabilityMetricDataParams, + regionCode: string, metricToken: string, ): Promise> => { const isMockEnabled = apiConfig['metrics-for-manager'] === 'mock'; console.info('[MOCK-ADAPTER][fetchChartData] Mock enabled -> ', isMockEnabled); return isMockEnabled ? fetchChartDataFromMock(params) - : fetchChartDataFromApi(params, metricToken); + : fetchChartDataFromApi(params, regionCode, metricToken); }; diff --git a/packages/manager/modules/metrics-to-customer/src/__tests__/MetricsToCustomer.module.spec.tsx b/packages/manager/modules/metrics-to-customer/src/__tests__/MetricsToCustomer.module.spec.tsx index 3a9c4fc167f5..f11dcd8bc18e 100644 --- a/packages/manager/modules/metrics-to-customer/src/__tests__/MetricsToCustomer.module.spec.tsx +++ b/packages/manager/modules/metrics-to-customer/src/__tests__/MetricsToCustomer.module.spec.tsx @@ -52,7 +52,7 @@ vi.mock('@/routes/routes', () => ({ getObservabilityRoute: getObservabilityRouteMock, })); -// Mock useIamResourceLocation hook +// Mock data hooks vi.mock('@/data/hooks', () => ({ useIamResourceLocation: () => ({ isLoading: false, @@ -64,6 +64,12 @@ vi.mock('@/data/hooks', () => ({ }, error: null, }), + useIamRegionsAndCapabilitiesMetrics: () => ({ + isPending: false, + isSuccess: true, + regions: [], + capabilitiesMetrics: [], + }), })); // Mock react-i18next diff --git a/packages/manager/modules/metrics-to-customer/src/components/subscriptions/TenantsSubscriptionsDrawer.component.tsx b/packages/manager/modules/metrics-to-customer/src/components/subscriptions/TenantsSubscriptionsDrawer.component.tsx index a1840c86e57c..b6fdb54dc3c9 100644 --- a/packages/manager/modules/metrics-to-customer/src/components/subscriptions/TenantsSubscriptionsDrawer.component.tsx +++ b/packages/manager/modules/metrics-to-customer/src/components/subscriptions/TenantsSubscriptionsDrawer.component.tsx @@ -47,7 +47,7 @@ const TenantsSubscriptionsDrawer = ({ const { regionCodes, regionLabels } = useMemo( () => ({ - regionCodes: regions.map(({ code }) => code), + regionCodes: regions.map(({ name }) => name), regionLabels: regions.map(({ label }) => label), }), [regions] diff --git a/packages/manager/modules/metrics-to-customer/src/contexts/Dashboard.context.tsx b/packages/manager/modules/metrics-to-customer/src/contexts/Dashboard.context.tsx index ec01f17dc390..56e158575024 100644 --- a/packages/manager/modules/metrics-to-customer/src/contexts/Dashboard.context.tsx +++ b/packages/manager/modules/metrics-to-customer/src/contexts/Dashboard.context.tsx @@ -5,7 +5,6 @@ import { DashboardContextType } from '@/contexts/Dashboard.context.type'; import { useMetricsToCustomerContext } from '@/contexts/MetricsToCustomer.context'; import { TimeRangeOption } from '@/types/TimeRangeOption.type'; import { calculateDateTimeRange } from '@/utils/dateTimeUtils'; -import { isRegionAvailable } from '@/utils/metrics.utils'; export interface DashboardState { isLoading: string | undefined; @@ -37,11 +36,10 @@ export const DashboardProvider = ({ children, context = {} }: DashboardProviderP selectedTimeOption, startDateTime, endDateTime, - regionAvailable, } = context; const { - state: { regions }, + state: { capabilitiesMetrics }, } = useMetricsToCustomerContext(); const initialSelectedTimeOption = @@ -57,11 +55,6 @@ export const DashboardProvider = ({ children, context = {} }: DashboardProviderP endDateTime: initialEndDateTime, }); - const computedRegionAvailable = useMemo( - () => regionAvailable ?? isRegionAvailable(regions), - [regionAvailable, regions], - ); - const { startDateTime: derivedStartDateTime, endDateTime: derivedEndDateTime } = useMemo(() => { if (state.selectedTimeOption.value === 'custom') { return { @@ -80,7 +73,7 @@ export const DashboardProvider = ({ children, context = {} }: DashboardProviderP ...state, startDateTime: derivedStartDateTime, endDateTime: derivedEndDateTime, - regionAvailable: computedRegionAvailable, + regionAvailable: capabilitiesMetrics, }, setState, }} diff --git a/packages/manager/modules/metrics-to-customer/src/contexts/MetricsToCustomer.type.tsx b/packages/manager/modules/metrics-to-customer/src/contexts/MetricsToCustomer.type.tsx index 59d5ba415067..39583de350b8 100644 --- a/packages/manager/modules/metrics-to-customer/src/contexts/MetricsToCustomer.type.tsx +++ b/packages/manager/modules/metrics-to-customer/src/contexts/MetricsToCustomer.type.tsx @@ -25,6 +25,7 @@ export type SubscriptionManagementConfig = type BaseMetricsToCustomerState = BaseM2CProperties & { regions: Region[]; + capabilitiesMetrics: boolean; }; export type MetricsToCustomerState = BaseMetricsToCustomerState & SubscriptionManagementConfig; diff --git a/packages/manager/modules/metrics-to-customer/src/data/api/metrics.ts b/packages/manager/modules/metrics-to-customer/src/data/api/metrics.ts index fa04b563e3fe..a35692830002 100644 --- a/packages/manager/modules/metrics-to-customer/src/data/api/metrics.ts +++ b/packages/manager/modules/metrics-to-customer/src/data/api/metrics.ts @@ -35,6 +35,7 @@ export const getMetricKindByName = async ({ export async function fetchChartData( payload: ObservabilityMetricDataParams, + regionCode: string, metricToken: string, ): Promise> { const { query, start, end, step } = payload; @@ -44,6 +45,7 @@ export async function fetchChartData( start, end, step, + regionCode, metricToken, }); diff --git a/packages/manager/modules/metrics-to-customer/src/data/api/metricsClient.ts b/packages/manager/modules/metrics-to-customer/src/data/api/metricsClient.ts index 784593fce107..788c946d269c 100644 --- a/packages/manager/modules/metrics-to-customer/src/data/api/metricsClient.ts +++ b/packages/manager/modules/metrics-to-customer/src/data/api/metricsClient.ts @@ -24,10 +24,13 @@ export interface PrometheusResult { }; } + +const getMetricForManagerBaseUrl = (regionCode: string) => + `https://metrics-for-manager.${regionCode}.technicalapis.ovh.net/m4m-single-endpoint-proxy/api/v1`; + // Create prometheus axios instance similar to v2 client -const metricForManagerClient = axios.create({ - baseURL: 'https://metrics-for-manager.gra.technicalapis.ovh.net/m4m-single-endpoint-proxy/api/v1', -}); +// NOTE: baseURL is set per-request to support dynamic regions. +const metricForManagerClient = axios.create(); // Add request interceptor for headers (same pattern as v2 client) metricForManagerClient.interceptors.request.use((config: InternalAxiosRequestConfig) => { @@ -85,6 +88,7 @@ export const prometheusApiClient = { }; export interface FetchPrometheusDataParams extends PrometheusQueryParams { + regionCode: string; metricToken: string; signal?: AbortSignal; } @@ -94,10 +98,11 @@ export const fetchPrometheusData = async ({ start, end, step, + regionCode, metricToken, signal, }: FetchPrometheusDataParams): Promise => { - + const baseURL = getMetricForManagerBaseUrl(regionCode); const { data } = await prometheusApiClient.get( '/query_range', { @@ -108,9 +113,10 @@ export const fetchPrometheusData = async ({ step, }, signal, + baseURL, headers: { - Authorization: `Bearer ${metricToken}` - } + Authorization: `Bearer ${metricToken}`, + }, }, ); diff --git a/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/getChartDataOptions.ts b/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/getChartDataOptions.ts index 7e6928b7aaa2..951729f2cf25 100644 --- a/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/getChartDataOptions.ts +++ b/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/getChartDataOptions.ts @@ -8,12 +8,13 @@ import { MetricData } from '@/types/observability.type'; export const getChartDataOptions = ( payload: RequestPayload, refreshInterval: number, + regionCode: string, metricToken: string, enabled = true, ) => { return queryOptions({ - queryKey: getChartDataQueryKey(payload, metricToken), - queryFn: (): Promise> => fetchChartData(payload, metricToken), + queryKey: getChartDataQueryKey(payload, regionCode, metricToken), + queryFn: (): Promise> => fetchChartData(payload, regionCode, metricToken), refetchInterval: refreshInterval > 0 ? refreshInterval * 1000 : false, enabled, }); diff --git a/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/getChartDataQueryKey.ts b/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/getChartDataQueryKey.ts index 19748cb66ba6..21e25a3df4df 100644 --- a/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/getChartDataQueryKey.ts +++ b/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/getChartDataQueryKey.ts @@ -1,6 +1,6 @@ import { RequestPayload } from '@/types/RequestPayload.type'; -export const getChartDataQueryKey = (payload: RequestPayload, metricToken: string) => +export const getChartDataQueryKey = (payload: RequestPayload, regionCode: string, metricToken: string) => [ 'chartData', 'type', @@ -13,6 +13,8 @@ export const getChartDataQueryKey = (payload: RequestPayload, metricToken: strin payload.end, 'step', payload.step, + 'regionCode', + regionCode, 'metricToken', metricToken, ] as const; diff --git a/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/useChartData.ts b/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/useChartData.ts index 1dee74d03576..02f1970d82ff 100644 --- a/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/useChartData.ts +++ b/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/useChartData.ts @@ -6,7 +6,9 @@ import { RequestPayload } from '@/types/RequestPayload.type'; export const useChartData = ( payload: RequestPayload, refreshInterval: number, + regionCode: string, metricToken: string, + fetchData = true, ) => { - return useQuery(getChartDataOptions(payload, refreshInterval, metricToken)); + return useQuery(getChartDataOptions(payload, refreshInterval, regionCode, metricToken, fetchData)); }; diff --git a/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/useChartWithData.ts b/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/useChartWithData.ts index 6bcf373efa6f..4cb6548434d5 100644 --- a/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/useChartWithData.ts +++ b/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/useChartWithData.ts @@ -19,7 +19,9 @@ type UseChartWithDataParams = { endDateTime?: number; selectedTimeOption: TimeRangeOption; refreshInterval: number; + regionCode: string; metricToken: string; + fetchData?: boolean; }; export const useChartWithData = ({ @@ -31,7 +33,9 @@ export const useChartWithData = ({ endDateTime, selectedTimeOption, refreshInterval, + regionCode, metricToken, + fetchData = true, }: UseChartWithDataParams) => { const queryClient = useQueryClient(); @@ -66,10 +70,10 @@ export const useChartWithData = ({ error: dataError, isError: isDataError, refetch, - } = useChartData(requestPayload, refreshInterval, metricToken); + } = useChartData(requestPayload, refreshInterval, regionCode, metricToken, fetchData); const cancel = () => queryClient.cancelQueries({ - queryKey: getChartDataQueryKey(requestPayload, metricToken), + queryKey: getChartDataQueryKey(requestPayload, regionCode, metricToken), exact: true, }); diff --git a/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/useMultipleChartData.ts b/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/useMultipleChartData.ts index 3eb40a6035ea..599007fb3ee2 100644 --- a/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/useMultipleChartData.ts +++ b/packages/manager/modules/metrics-to-customer/src/data/hooks/dashboards/useMultipleChartData.ts @@ -13,6 +13,7 @@ type UseMultipleChartDataParams = { endDateTime?: number; selectedTimeOption: TimeRangeOption; refreshInterval: number; + regionCode: string; metricToken: string; fetchData?: boolean; }; @@ -23,6 +24,7 @@ export const useMultipleChartData = ({ endDateTime, selectedTimeOption, refreshInterval, + regionCode, metricToken, fetchData = true, }: UseMultipleChartDataParams): ChartQueryResult[] => { @@ -42,7 +44,7 @@ export const useMultipleChartData = ({ step, type: 'query_range', }; - const query = getChartDataOptions(payload, refreshInterval, metricToken, fetchData); + const query = getChartDataOptions(payload, refreshInterval, regionCode, metricToken, fetchData); return { ...query, diff --git a/packages/manager/modules/metrics-to-customer/src/data/hooks/iam/useIamRegionsAndCapabilitiesMetrics.hook.ts b/packages/manager/modules/metrics-to-customer/src/data/hooks/iam/useIamRegionsAndCapabilitiesMetrics.hook.ts new file mode 100644 index 000000000000..dd7863e53891 --- /dev/null +++ b/packages/manager/modules/metrics-to-customer/src/data/hooks/iam/useIamRegionsAndCapabilitiesMetrics.hook.ts @@ -0,0 +1,41 @@ +import { useLocation } from '@/data/hooks/locations/useLocations.hook'; +import { useIamResourceTags } from '@/data/hooks/iam/useIamResourceTags.hook'; + +export const useIamRegionsAndCapabilitiesMetrics = (resourceURN: string) => { + const { + data: iamTags, + isLoading: isIamTagsLoading, + isSuccess: isIamTagsSuccess, + } = useIamResourceTags(resourceURN, [ + 'ovh:region', + 'ovh:capabilities:metrics', + ]); + + const regionName = iamTags?.['ovh:region']; + + const { + data: location, + isLoading: isLocationLoading, + isSuccess: isLocationSuccess, + } = useLocation(regionName ?? ''); + + const regions = [ + { + code: location?.code ?? '', + name: location?.name ?? '', + label: location?.location ?? '', + }, + ]; + + const capabilitiesMetrics = + iamTags?.['ovh:capabilities:metrics'] === 'true'; + + return { + isPending: isIamTagsLoading || isLocationLoading, + isSuccess: isIamTagsSuccess && isLocationSuccess, + regions, + capabilitiesMetrics, + tags: iamTags, + }; +}; + diff --git a/packages/manager/modules/metrics-to-customer/src/data/hooks/iam/useIamResource.hook.ts b/packages/manager/modules/metrics-to-customer/src/data/hooks/iam/useIamResource.hook.ts index 7b6bb6002ad6..67b164f2ce2c 100644 --- a/packages/manager/modules/metrics-to-customer/src/data/hooks/iam/useIamResource.hook.ts +++ b/packages/manager/modules/metrics-to-customer/src/data/hooks/iam/useIamResource.hook.ts @@ -2,7 +2,6 @@ import { UseQueryOptions, useQuery } from '@tanstack/react-query'; import { getResource } from '@/data/api/iam.api'; import { IamResourcesResponse } from '@/types/iam.type'; -import { useLocation } from '@/data/hooks/locations/useLocations.hook'; export const getIamResourceQueryKey = (resourceURN: string) => [ 'resourceURN', @@ -23,49 +22,3 @@ export const useIamResource = ( ...options, }); }; - -export const useIamResourceRegion = (resourceURN: string) => { - const { data, isLoading, isFetching, error, isSuccess } = useIamResource( - resourceURN, - ); - - const resource = data?.[0]; - const region = resource?.tags?.['ovh:region']; - const notFound = isSuccess && !region; - - return { - data: region, - resource, - isLoading: isLoading || isFetching, - isSuccess: isSuccess && !!region, - isError: !!error || notFound, - error: error ?? (notFound ? new Error(`Region not found in IAM resource tags for URN "${resourceURN}".`) : null), - }; -}; - -export const useIamResourceLocation = (resourceURN: string) => { - const { - data: region, - resource, - isLoading: isRegionLoading, - error: regionError, - } = useIamResourceRegion(resourceURN); - - const { - data: location, - isLoading: isLocationLoading, - isSuccess, - isError: isLocationError, - error: locationError, - } = useLocation(region || ''); - - return { - data: location, - region, - resource, - isLoading: isRegionLoading || isLocationLoading, - isSuccess, - isError: !!regionError || isLocationError, - error: regionError || locationError, - }; -}; diff --git a/packages/manager/modules/metrics-to-customer/src/data/hooks/iam/useIamResourceTags.hook.ts b/packages/manager/modules/metrics-to-customer/src/data/hooks/iam/useIamResourceTags.hook.ts new file mode 100644 index 000000000000..8d007cff09d0 --- /dev/null +++ b/packages/manager/modules/metrics-to-customer/src/data/hooks/iam/useIamResourceTags.hook.ts @@ -0,0 +1,41 @@ +import { useIamResource } from '@/data/hooks/iam/useIamResource.hook'; + +export const useIamResourceTags = ( + resourceURN: string, + tagKeys: string[], +) => { + const { data, isLoading, isFetching, error, isSuccess } = useIamResource( + resourceURN, + ); + + const resource = data?.[0]; + + const tags = tagKeys.reduce>( + (acc, key) => { + acc[key] = resource?.tags?.[key]; + return acc; + }, + {}, + ); + + const allTagsMissing = + isSuccess && tagKeys.every((key) => tags[key] === undefined); + + return { + data: tags, + resource, + isLoading: isLoading || isFetching, + isSuccess: isSuccess && !allTagsMissing, + isError: !!error || allTagsMissing, + error: + error ?? + (allTagsMissing + ? new Error( + `Tags "${tagKeys.join( + ', ', + )}" not found in IAM resource tags for URN "${resourceURN}".`, + ) + : null), + }; +}; + diff --git a/packages/manager/modules/metrics-to-customer/src/data/hooks/index.ts b/packages/manager/modules/metrics-to-customer/src/data/hooks/index.ts index b6473a0f8621..81d31150944f 100644 --- a/packages/manager/modules/metrics-to-customer/src/data/hooks/index.ts +++ b/packages/manager/modules/metrics-to-customer/src/data/hooks/index.ts @@ -1,4 +1,6 @@ export * from '@/data/hooks/dashboards'; export * from '@/data/hooks/iam/useIamResource.hook'; +export * from '@/data/hooks/iam/useIamResourceTags.hook'; +export * from '@/data/hooks/iam/useIamRegionsAndCapabilitiesMetrics.hook'; export * from '@/data/hooks/locations/useLocations.hook'; export * from '@/data/hooks/metrics'; diff --git a/packages/manager/modules/metrics-to-customer/src/data/hooks/tenants/useTenantsWithSubscriptions.ts b/packages/manager/modules/metrics-to-customer/src/data/hooks/tenants/useTenantsWithSubscriptions.ts index e5f077ac3dd7..6e4bb2bbe201 100644 --- a/packages/manager/modules/metrics-to-customer/src/data/hooks/tenants/useTenantsWithSubscriptions.ts +++ b/packages/manager/modules/metrics-to-customer/src/data/hooks/tenants/useTenantsWithSubscriptions.ts @@ -23,7 +23,7 @@ export const useTenantsWithSubscriptions = ( const { iamTags: additionalIamTags, queryOptions } = options || {}; const iamTags = useMemo(() => { - const validRegions = regions.map(({ code }) => code).filter((region) => region && region.trim() !== ''); + const validRegions = regions.map(({ name }) => name).filter((region) => region && region.trim() !== ''); if ( validRegions.length === 0 && diff --git a/packages/manager/modules/metrics-to-customer/src/hooks/useDashboardData.ts b/packages/manager/modules/metrics-to-customer/src/hooks/useDashboardData.ts index fb35dcc9f01a..cac7edc531b1 100644 --- a/packages/manager/modules/metrics-to-customer/src/hooks/useDashboardData.ts +++ b/packages/manager/modules/metrics-to-customer/src/hooks/useDashboardData.ts @@ -15,6 +15,7 @@ import { buildQueryWithResourceUrn } from '@/utils/metrics.utils'; * @param resourceName * @param productType * @param resourceURN + * @param regionCode * @param metricToken * @param fetchData - If false, only retrieves dashboard config without fetching chart data * @returns Object containing: @@ -25,6 +26,7 @@ export const useDashboardData = ( resourceName: string, productType: string, resourceURN: string, + regionCode: string, metricToken: string, fetchData = true, ) => { @@ -53,6 +55,7 @@ export const useDashboardData = ( endDateTime, selectedTimeOption, refreshInterval, + regionCode, metricToken, fetchData, }); diff --git a/packages/manager/modules/metrics-to-customer/src/pages/metrics/dashboards/Dashboard.page.tsx b/packages/manager/modules/metrics-to-customer/src/pages/metrics/dashboards/Dashboard.page.tsx index 590e7cc35405..ebc1fad727e6 100644 --- a/packages/manager/modules/metrics-to-customer/src/pages/metrics/dashboards/Dashboard.page.tsx +++ b/packages/manager/modules/metrics-to-customer/src/pages/metrics/dashboards/Dashboard.page.tsx @@ -20,6 +20,7 @@ const DashboardPage = () => { const { t } = useTranslation(NAMESPACES.DASHBOARDS); const { state: { resourceName, productType, resourceURN, regions, } } = useMetricsToCustomerContext(); + const { code: regionCode = '', label: regionLabel = '' } = regions[0] ?? {}; const { state: { regionAvailable } } = useDashboardContext(); const { data: metricToken } = useMetricToken({ resourceName }); @@ -28,6 +29,7 @@ const DashboardPage = () => { resourceName, productType, resourceURN, + regionCode, metricToken ?? '', regionAvailable, ); @@ -48,11 +50,11 @@ const DashboardPage = () => { { !regionAvailable && ( - + - {t(`${NAMESPACES.MODULE}:metrics_region_not_available`, { region: regions[0]?.label })} + {t(`${NAMESPACES.MODULE}:metrics_region_not_available`, { region: regionLabel })} diff --git a/packages/manager/modules/metrics-to-customer/src/pages/metrics/dashboards/DashboardWidgetModal.page.tsx b/packages/manager/modules/metrics-to-customer/src/pages/metrics/dashboards/DashboardWidgetModal.page.tsx index a6a33239c948..4c98a255fcc6 100644 --- a/packages/manager/modules/metrics-to-customer/src/pages/metrics/dashboards/DashboardWidgetModal.page.tsx +++ b/packages/manager/modules/metrics-to-customer/src/pages/metrics/dashboards/DashboardWidgetModal.page.tsx @@ -1,4 +1,4 @@ -import { useMemo } from 'react'; +import { Suspense, useMemo } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; @@ -8,6 +8,8 @@ import { Button, MESSAGE_COLOR, Message, + MessageBody, + MessageIcon, Modal, ModalBody, ModalContent, @@ -39,14 +41,11 @@ const DashboardWidgetModal = () => { const { widgetId } = useParams(); - const { state } = useMetricsToCustomerContext(); + const { state: { resourceName, productType, resourceURN, regions, } } = useMetricsToCustomerContext(); + const { code: regionCode = '', label: regionLabel = '' } = regions[0] ?? {}; const { state: dashboardState, setState: setDashboardState } = useDashboardContext(); - const resourceName = state.resourceName ?? ''; - const productType = state.productType ?? ''; - const resourceURN = state.resourceURN ?? ''; - const { data: metricToken, isLoading: isMetricTokenLoading } = useMetricToken({ resourceName }); const { @@ -54,6 +53,7 @@ const DashboardWidgetModal = () => { endDateTime, selectedTimeOption, refreshInterval, + regionAvailable, } = dashboardState; const { isLoading, config, data, refetch, cancel } = useChartWithData({ @@ -65,7 +65,9 @@ const DashboardWidgetModal = () => { endDateTime, selectedTimeOption, refreshInterval, + regionCode, metricToken: metricToken ?? '', + fetchData: regionAvailable, }); const globalLoading = useMemo(() => isMetricTokenLoading || isLoading, [isMetricTokenLoading, isLoading]); @@ -108,62 +110,84 @@ const DashboardWidgetModal = () => { const { id, title, chart } = config; return ( - - -
-
- {tDashboardTexts(title)} -
-
- -
-
- - {globalLoading ? ( -
- -
- ) : ( -
- - type={chart.type} - chartConfig={chart} - id={id} - title={title} - data={data ?? []} - isLoading={false} - isFullscreen={true} - state={dashboardState} - /> -
- )} -
+ + + +
- + {tDashboardTexts(title)} +
+
+
- -
-
+ + { + !regionAvailable && ( + + + + + {t(`${NAMESPACES.MODULE}:metrics_region_not_available`, { region: regionLabel })} + + + + ) + } + + + { + regionAvailable ? <> + { + globalLoading ?
+ +
+ : ( +
+ + type={chart.type} + chartConfig={chart} + id={id} + title={title} + data={data ?? []} + isLoading={false} + isFullscreen={true} + state={dashboardState} + /> +
+ ) + } + + : null + } +
+
+ +
+
+
+ + +
); }; export default DashboardWidgetModal; diff --git a/packages/manager/modules/metrics-to-customer/src/types/region.type.ts b/packages/manager/modules/metrics-to-customer/src/types/region.type.ts index 5f890271f1de..b6705a56e881 100644 --- a/packages/manager/modules/metrics-to-customer/src/types/region.type.ts +++ b/packages/manager/modules/metrics-to-customer/src/types/region.type.ts @@ -1,4 +1,5 @@ export type Region = { code: string; + name: string; label: string; }; diff --git a/packages/manager/modules/metrics-to-customer/src/utils/__tests__/metrics.utils.spec.ts b/packages/manager/modules/metrics-to-customer/src/utils/__tests__/metrics.utils.spec.ts index 51fc01ce6cc0..5d6fcd25f4ca 100644 --- a/packages/manager/modules/metrics-to-customer/src/utils/__tests__/metrics.utils.spec.ts +++ b/packages/manager/modules/metrics-to-customer/src/utils/__tests__/metrics.utils.spec.ts @@ -460,8 +460,9 @@ describe('metrics.utils', () => { // Arrange const regions: Region[] = [ { - code: 'eu-west-gra', - name: 'Gravelines', + code: 'gra', + label: 'Gravelines', + name: 'eu-west-gra', }, ]; @@ -519,12 +520,14 @@ describe('metrics.utils', () => { // Arrange const regions: Region[] = [ { - code: 'us-east-1', - name: 'US East', + code: 'us', + label: 'US East', + name: 'us-east-1', }, { - code: 'eu-west-gra', - name: 'Gravelines', + code: 'gra', + label: 'Gravelines', + name: 'eu-west-gra', }, ]; @@ -540,11 +543,13 @@ describe('metrics.utils', () => { const regions: Region[] = [ { code: 'us-east-1', - name: 'US East', + label: 'US East', + name: 'us-east-1', }, { - code: 'ap-south-1', - name: 'Asia Pacific', + code: 'ap', + label: 'Asia Pacific', + name: 'ap-south-1', }, ]; diff --git a/packages/manager/modules/metrics-to-customer/src/utils/metrics.utils.ts b/packages/manager/modules/metrics-to-customer/src/utils/metrics.utils.ts index 20e69400af72..a109722ae8a2 100644 --- a/packages/manager/modules/metrics-to-customer/src/utils/metrics.utils.ts +++ b/packages/manager/modules/metrics-to-customer/src/utils/metrics.utils.ts @@ -9,7 +9,7 @@ import { Region } from '@/types/region.type'; * @returns true if at least one region supports metric data, false otherwise */ export const isRegionAvailable = (regions: Region[]): boolean => { - return regions.some((region) => REGIONS_AVAILABLES.includes(region.code ?? '')); + return regions.some((region) => REGIONS_AVAILABLES.includes(region.name ?? '')); }; // TODO: update the chart adapter when wired to the real metric APIs.