diff --git a/locales/data.json b/locales/data.json index 508a216ce..046f771c8 100644 --- a/locales/data.json +++ b/locales/data.json @@ -8207,6 +8207,12 @@ "value": "This page shows filtered results. To undo filters, clear filters on the previous page." } ], + "finalization": [ + { + "type": 0, + "value": "Finalization" + } + ], "forDate": [ { "type": 1, @@ -11775,6 +11781,12 @@ "value": "Rate must be a positive number" } ], + "providerDetails": [ + { + "type": 0, + "value": "Integrations details" + } + ], "pvcTitle": [ { "type": 0, diff --git a/locales/translations.json b/locales/translations.json index 8c842ffb3..5141319cb 100644 --- a/locales/translations.json +++ b/locales/translations.json @@ -336,6 +336,7 @@ "filterByValuesAriaLabel": "Values", "filteredBy": "Filtered by", "filteredByWarning": "This page shows filtered results. To undo filters, clear filters on the previous page.", + "finalization": "Finalization", "forDate": "{value} for {dateRange}", "gcp": "Google Cloud Platform", "gcpComputeTitle": "Compute instances usage", @@ -505,6 +506,7 @@ "priceListEmptyRateDesc": "To add rates to the price list, click on the \"Add\" rate button above.", "priceListNumberRate": "Rate must be a number", "priceListPosNumberRate": "Rate must be a positive number", + "providerDetails": "Integrations details", "pvcTitle": "Persistent Volume Claims", "rate": "Rate", "rawCostDesc": "The costs reported by a cloud provider without any cost model calculations applied.", diff --git a/src/locales/messages.ts b/src/locales/messages.ts index ba70f69bd..c9b82c04f 100644 --- a/src/locales/messages.ts +++ b/src/locales/messages.ts @@ -2124,6 +2124,11 @@ export default defineMessages({ description: 'This page shows filtered results. To undo filters, clear filters on the previous page.', id: 'filteredByWarning', }, + finalization: { + defaultMessage: 'Finalization', + description: 'Finalization', + id: 'finalization', + }, forDate: { defaultMessage: '{value} for {dateRange}', description: '{value} for {Jan 1-31}', @@ -3137,6 +3142,11 @@ export default defineMessages({ description: 'Rate must be a positive number', id: 'priceListPosNumberRate', }, + providerDetails: { + defaultMessage: 'Integrations details', + description: 'Integrations details', + id: 'providerDetails', + }, pvcTitle: { defaultMessage: 'Persistent Volume Claims', description: 'Persistent Volume Claims', diff --git a/src/routes/details/awsDetails/awsDetails.tsx b/src/routes/details/awsDetails/awsDetails.tsx index e7bf6d5b1..581496b2a 100644 --- a/src/routes/details/awsDetails/awsDetails.tsx +++ b/src/routes/details/awsDetails/awsDetails.tsx @@ -20,6 +20,7 @@ import { Loading } from 'routes/components/page/loading'; import { NoData } from 'routes/components/page/noData'; import { NoProviders } from 'routes/components/page/noProviders'; import { NotAvailable } from 'routes/components/page/notAvailable'; +import { ProviderDetails } from 'routes/details/components/providerDetails'; import { getIdKeyForGroupBy } from 'routes/utils/computedReport/getComputedAwsReportItems'; import type { ComputedReportItem } from 'routes/utils/computedReport/getComputedReportItems'; import { getUnsortedComputedReportItems } from 'routes/utils/computedReport/getComputedReportItems'; @@ -36,6 +37,7 @@ import { handleOnSort, } from 'routes/utils/queryNavigate'; import { createMapStateToProps, FetchStatus } from 'store/common'; +import { FeatureToggleSelectors } from 'store/featureToggle'; import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { formatPath } from 'utils/paths'; @@ -52,6 +54,7 @@ import { DetailsToolbar } from './detailsToolbar'; interface AwsDetailsStateProps { costType: string; currency?: string; + isAccountInfoEmptyStateToggleEnabled?: boolean; providers: Providers; providersError: AxiosError; providersFetchStatus: FetchStatus; @@ -365,6 +368,7 @@ class AwsDetails extends React.Component { costType, currency, intl, + isAccountInfoEmptyStateToggleEnabled, providers, providersFetchStatus, query, @@ -392,9 +396,17 @@ class AwsDetails extends React.Component { return ; } if (!hasCurrentMonthData(providers)) { - return ; + return ( + : undefined + } + title={title} + /> + ); } } + return (
const { currency, intl, + isAccountInfoEmptyStateToggleEnabled, providers, providersFetchStatus, query, @@ -352,9 +356,17 @@ class AzureDetails extends React.Component return ; } if (!hasCurrentMonthData(providers)) { - return ; + return ( + : undefined + } + title={title} + /> + ); } } + return (
= ({ provider }: CloudDataProps) => { {intl.formatMessage(messages.dataDetailsAvailability)} @@ -53,8 +54,8 @@ const CloudData: React.FC = ({ provider }: CloudDataProps) => { {intl.formatMessage(messages.dataDetailsRetrieval)} @@ -65,8 +66,8 @@ const CloudData: React.FC = ({ provider }: CloudDataProps) => { {intl.formatMessage(messages.dataDetailsProcessing)} diff --git a/src/routes/details/components/providerDetails/clusterDetails/components/clusterData.tsx b/src/routes/details/components/providerDetails/components/clusterData.tsx similarity index 91% rename from src/routes/details/components/providerDetails/clusterDetails/components/clusterData.tsx rename to src/routes/details/components/providerDetails/components/clusterData.tsx index 496dce0c2..3a4ae83e8 100644 --- a/src/routes/details/components/providerDetails/clusterDetails/components/clusterData.tsx +++ b/src/routes/details/components/providerDetails/components/clusterData.tsx @@ -3,12 +3,13 @@ import type { Provider } from 'api/providers'; import messages from 'locales/messages'; import React from 'react'; import { useIntl } from 'react-intl'; -import { styles } from 'routes/details/components/providerDetails/clusterDetails/clusterDetails.styles'; -import { formatDate } from 'routes/details/components/providerDetails/clusterDetails/utils/format'; -import { getProgressStepIcon } from 'routes/details/components/providerDetails/clusterDetails/utils/icon'; -import { getProviderAvailability } from 'routes/details/components/providerDetails/clusterDetails/utils/status'; -import { getProgressStepVariant } from 'routes/details/components/providerDetails/clusterDetails/utils/variant'; import { SourceLink } from 'routes/details/components/providerDetails/components/sourceLink'; +import { formatDate } from 'routes/details/components/providerDetails/utils/format'; +import { getProgressStepIcon } from 'routes/details/components/providerDetails/utils/icon'; +import { getProviderAvailability } from 'routes/details/components/providerDetails/utils/status'; +import { getProgressStepVariant } from 'routes/details/components/providerDetails/utils/variant'; + +import { styles } from './component.styles'; interface ClusterDataOwnProps { provider: Provider; diff --git a/src/routes/details/components/providerDetails/clusterDetails/clusterDetails.styles.ts b/src/routes/details/components/providerDetails/components/component.styles.ts similarity index 78% rename from src/routes/details/components/providerDetails/clusterDetails/clusterDetails.styles.ts rename to src/routes/details/components/providerDetails/components/component.styles.ts index 33f39d5aa..44aa60ec0 100644 --- a/src/routes/details/components/providerDetails/clusterDetails/clusterDetails.styles.ts +++ b/src/routes/details/components/providerDetails/components/component.styles.ts @@ -1,4 +1,3 @@ -import global_BackgroundColor_light_100 from '@patternfly/react-tokens/dist/js/global_BackgroundColor_light_100'; import global_disabled_color_100 from '@patternfly/react-tokens/dist/js/global_disabled_color_100'; import global_FontSize_xs from '@patternfly/react-tokens/dist/js/global_FontSize_xs'; import global_spacer_lg from '@patternfly/react-tokens/dist/js/global_spacer_lg'; @@ -7,16 +6,10 @@ import global_spacer_sm from '@patternfly/react-tokens/dist/js/global_spacer_sm' import type React from 'react'; export const styles = { - dataDetailsButton: { - fontSize: global_FontSize_xs.value, - }, description: { color: global_disabled_color_100.value, fontSize: global_FontSize_xs.value, }, - loading: { - backgroundColor: global_BackgroundColor_light_100.value, - }, sourceLink: { fontSize: global_FontSize_xs.value, }, diff --git a/src/routes/details/components/providerDetails/clusterDetails/components/costData.tsx b/src/routes/details/components/providerDetails/components/finalization.tsx similarity index 63% rename from src/routes/details/components/providerDetails/clusterDetails/components/costData.tsx rename to src/routes/details/components/providerDetails/components/finalization.tsx index 43adb3913..6c9d784d5 100644 --- a/src/routes/details/components/providerDetails/clusterDetails/components/costData.tsx +++ b/src/routes/details/components/providerDetails/components/finalization.tsx @@ -1,36 +1,39 @@ import { ProgressStep, ProgressStepper, Text, TextContent, TextVariants } from '@patternfly/react-core'; import type { Provider } from 'api/providers'; +import { ProviderType } from 'api/providers'; import messages from 'locales/messages'; import React from 'react'; import { useIntl } from 'react-intl'; -import { styles } from 'routes/details/components/providerDetails/clusterDetails/clusterDetails.styles'; -import { formatDate } from 'routes/details/components/providerDetails/clusterDetails/utils/format'; -import { getProgressStepIcon } from 'routes/details/components/providerDetails/clusterDetails/utils/icon'; -import { getProgressStepVariant } from 'routes/details/components/providerDetails/clusterDetails/utils/variant'; +import { formatDate } from 'routes/details/components/providerDetails/utils/format'; +import { getProgressStepIcon } from 'routes/details/components/providerDetails/utils/icon'; +import { getProgressStepVariant } from 'routes/details/components/providerDetails/utils/variant'; -interface CostDataOwnProps { +import { styles } from './component.styles'; + +interface FinalizationDataOwnProps { provider: Provider; + providerType: ProviderType; } -type CostDataProps = CostDataOwnProps; +type FinalizationDataProps = FinalizationDataOwnProps; -const CostData: React.FC = ({ provider }: CostDataProps) => { +const Finalization: React.FC = ({ provider, providerType }: FinalizationDataProps) => { const intl = useIntl(); if (!provider) { return null; } + const title = intl.formatMessage( + providerType === ProviderType.ocp ? messages.dataDetailsCostManagementData : messages.finalization + ); + return ( <> - {intl.formatMessage(messages.dataDetailsCostManagementData)} + {title} - + = ({ provider }: CostDataProps) => { ); }; -export { CostData }; +export { Finalization }; diff --git a/src/routes/details/components/providerDetails/clusterDetails/components/overallStatus.tsx b/src/routes/details/components/providerDetails/components/overallStatus.tsx similarity index 69% rename from src/routes/details/components/providerDetails/clusterDetails/components/overallStatus.tsx rename to src/routes/details/components/providerDetails/components/overallStatus.tsx index 131122660..00e4bc719 100644 --- a/src/routes/details/components/providerDetails/clusterDetails/components/overallStatus.tsx +++ b/src/routes/details/components/providerDetails/components/overallStatus.tsx @@ -7,23 +7,26 @@ import React from 'react'; import type { MessageDescriptor } from 'react-intl'; import { useIntl } from 'react-intl'; import { useSelector } from 'react-redux'; -import { styles } from 'routes/details/components/providerDetails/clusterDetails/clusterDetails.styles'; -import { formatDate } from 'routes/details/components/providerDetails/clusterDetails/utils/format'; -import { getOverallStatusIcon } from 'routes/details/components/providerDetails/clusterDetails/utils/icon'; +import { formatDate } from 'routes/details/components/providerDetails/utils/format'; +import { getOverallStatusIcon } from 'routes/details/components/providerDetails/utils/icon'; import { getProviderAvailability, getProviderStatus, StatusType, -} from 'routes/details/components/providerDetails/clusterDetails/utils/status'; +} from 'routes/details/components/providerDetails/utils/status'; import { filterProviders } from 'routes/utils/providers'; import type { RootState } from 'store'; import type { FetchStatus } from 'store/common'; import { providersQuery, providersSelectors } from 'store/providers'; +import { styles } from './component.styles'; + interface OverallStatusOwnProps { clusterId?: string; isLastUpdated?: boolean; isStatusMsg?: boolean; + providerId?: string; + providerType: ProviderType; } interface OverallStatusStateProps { @@ -35,7 +38,13 @@ interface OverallStatusStateProps { type OverallStatusProps = OverallStatusOwnProps; -const OverallStatus: React.FC = ({ clusterId, isLastUpdated, isStatusMsg }: OverallStatusProps) => { +const OverallStatus: React.FC = ({ + clusterId, + isLastUpdated, + isStatusMsg, + providerId, + providerType, +}: OverallStatusProps) => { const { providers, providersError } = useMapToProps(); const intl = useIntl(); @@ -44,9 +53,11 @@ const OverallStatus: React.FC = ({ clusterId, isLastUpdated, } // Filter OCP providers to skip an extra API request - const ocpProviders = filterProviders(providers, ProviderType.ocp); - const clusterProvider = ocpProviders?.data?.find(val => val.authentication?.credentials?.cluster_id === clusterId); - const cloudProvider = providers?.data?.find(val => val.uuid === clusterProvider?.infrastructure?.uuid); + const filteredProviders = filterProviders(providers, providerType)?.data?.filter(data => data.status !== null); + const provider = filteredProviders?.find( + val => providerId === val.id || (clusterId && val.authentication?.credentials?.cluster_id === clusterId) + ); + const cloudProvider = providers?.data?.find(val => val.uuid === provider?.infrastructure?.uuid); const getOverallStatus = (): { lastUpdated: string; msg: MessageDescriptor; status: StatusType } => { let lastUpdated; @@ -54,9 +65,9 @@ const OverallStatus: React.FC = ({ clusterId, isLastUpdated, let status; const cloudAvailability = getProviderAvailability(cloudProvider); - const clusterAvailability = getProviderAvailability(clusterProvider); + const providerAvailability = getProviderAvailability(provider); const cloudStatus = getProviderStatus(cloudProvider, true); - const clusterStatus = getProviderStatus(clusterProvider); + const providerStatus = getProviderStatus(provider); const initializeState = (statusType: StatusType, state1, state2, state3, state4) => { if (msg && status) { @@ -65,31 +76,31 @@ const OverallStatus: React.FC = ({ clusterId, isLastUpdated, if (statusType === StatusType.complete) { // A cluster may not have an integration, so cloudProvider could be undefined if ( - (state1 === undefined || state1.status === statusType) && + (state1 === undefined || state1?.status === statusType) && (state2 === undefined || state2?.status === statusType) && (state3 === undefined || state3?.status === statusType) && (state4 === undefined || state4?.status === statusType) ) { - lastUpdated = state1.lastUpdated; - msg = state1.msg; + lastUpdated = state1?.lastUpdated; + msg = state1?.msg; status = statusType; } } else { if (state1?.status === statusType) { - lastUpdated = state1.lastUpdated; - msg = state1.msg; + lastUpdated = state1?.lastUpdated; + msg = state1?.msg; status = statusType; } else if (state2?.status === statusType) { - lastUpdated = state2.lastUpdated; - msg = state2.msg; + lastUpdated = state2?.lastUpdated; + msg = state2?.msg; status = statusType; } else if (state3?.status === statusType) { - lastUpdated = state3.lastUpdated; - msg = state3.msg; + lastUpdated = state3?.lastUpdated; + msg = state3?.msg; status = statusType; } else if (state4?.status === statusType) { - lastUpdated = state4.lastUpdated; - msg = state4.msg; + lastUpdated = state4?.lastUpdated; + msg = state4?.msg; status = statusType; } } @@ -97,11 +108,11 @@ const OverallStatus: React.FC = ({ clusterId, isLastUpdated, // Note: status is not synchronous; however, status shall be applied in order provided below (e.g., failed takes precedence over any other state). // Cloud availability takes precedence over cloud status, while cluster availability takes precedence over cluster status, and so on... - initializeState(StatusType.failed, cloudAvailability, clusterAvailability, cloudStatus, clusterStatus); - initializeState(StatusType.paused, cloudAvailability, clusterAvailability, cloudStatus, clusterStatus); - initializeState(StatusType.inProgress, cloudAvailability, clusterAvailability, cloudStatus, clusterStatus); // Availability won't likely have in-progress and pending states - initializeState(StatusType.pending, cloudAvailability, clusterAvailability, cloudStatus, clusterStatus); - initializeState(StatusType.complete, clusterStatus, cloudStatus, clusterAvailability, cloudAvailability); // Must display the cluster status msg here + initializeState(StatusType.failed, cloudAvailability, providerAvailability, cloudStatus, providerStatus); + initializeState(StatusType.paused, cloudAvailability, providerAvailability, cloudStatus, providerStatus); + initializeState(StatusType.inProgress, cloudAvailability, providerAvailability, cloudStatus, providerStatus); // Availability won't likely have in-progress and pending states + initializeState(StatusType.pending, cloudAvailability, providerAvailability, cloudStatus, providerStatus); + initializeState(StatusType.complete, providerStatus, cloudStatus, providerAvailability, cloudAvailability); // Must display the cluster status msg here return { lastUpdated, msg, status }; }; diff --git a/src/routes/details/components/providerDetails/components/sourceLink.styles.ts b/src/routes/details/components/providerDetails/components/sourceLink.styles.ts deleted file mode 100644 index 81c67d5f0..000000000 --- a/src/routes/details/components/providerDetails/components/sourceLink.styles.ts +++ /dev/null @@ -1,8 +0,0 @@ -import global_spacer_md from '@patternfly/react-tokens/dist/js/global_spacer_md'; -import type React from 'react'; - -export const styles = { - spacingRight: { - marginRight: global_spacer_md.value, - }, -} as { [className: string]: React.CSSProperties }; diff --git a/src/routes/details/components/providerDetails/components/sourceLink.tsx b/src/routes/details/components/providerDetails/components/sourceLink.tsx index 7e50d5c0d..e02c4a60a 100644 --- a/src/routes/details/components/providerDetails/components/sourceLink.tsx +++ b/src/routes/details/components/providerDetails/components/sourceLink.tsx @@ -5,7 +5,7 @@ import { useIntl } from 'react-intl'; import { normalize } from 'routes/details/components/providerDetails/utils/normailize'; import { getReleasePath } from 'utils/paths'; -import { styles } from './sourceLink.styles'; +import { styles } from './component.styles'; interface SourceLinkOwnProps { provider: Provider; diff --git a/src/routes/details/components/providerDetails/index.ts b/src/routes/details/components/providerDetails/index.ts new file mode 100644 index 000000000..61e26dae5 --- /dev/null +++ b/src/routes/details/components/providerDetails/index.ts @@ -0,0 +1,2 @@ +export { ProviderDetails } from './providerDetails'; +export { ProviderDetailsModal } from './providerDetailsModal'; diff --git a/src/routes/details/components/providerDetails/providerDetails.styles.ts b/src/routes/details/components/providerDetails/providerDetails.styles.ts new file mode 100644 index 000000000..baedf2d15 --- /dev/null +++ b/src/routes/details/components/providerDetails/providerDetails.styles.ts @@ -0,0 +1,12 @@ +import global_BackgroundColor_light_100 from '@patternfly/react-tokens/dist/js/global_BackgroundColor_light_100'; +import global_FontSize_xs from '@patternfly/react-tokens/dist/js/global_FontSize_xs'; +import type React from 'react'; + +export const styles = { + dataDetailsButton: { + fontSize: global_FontSize_xs.value, + }, + loading: { + backgroundColor: global_BackgroundColor_light_100.value, + }, +} as { [className: string]: React.CSSProperties }; diff --git a/src/routes/details/components/providerDetails/clusterDetails/clusterDetails.tsx b/src/routes/details/components/providerDetails/providerDetails.tsx similarity index 74% rename from src/routes/details/components/providerDetails/clusterDetails/clusterDetails.tsx rename to src/routes/details/components/providerDetails/providerDetails.tsx index 1b01d6208..5739a9c88 100644 --- a/src/routes/details/components/providerDetails/clusterDetails/clusterDetails.tsx +++ b/src/routes/details/components/providerDetails/providerDetails.tsx @@ -12,28 +12,28 @@ import type { RootState } from 'store'; import { FetchStatus } from 'store/common'; import { providersQuery, providersSelectors } from 'store/providers'; -import { styles } from './clusterDetails.styles'; -import { ClusterDetailsTable } from './clusterDetailsTable'; +import { styles } from './providerDetails.styles'; +import { ProviderDetailsTable } from './providerDetailsTable'; -interface ClusterDetailsOwnProps { - // TBD... +interface ProviderDetailsOwnProps { + providerType: ProviderType; } -interface ClusterDetailsStateProps { +interface ProviderDetailsStateProps { providers: Providers; providersError: AxiosError; providersFetchStatus: FetchStatus; providersQueryString: string; } -type ClusterDetailsProps = ClusterDetailsOwnProps; +type ProviderDetailsProps = ProviderDetailsOwnProps; -const ClusterDetails: React.FC = () => { +const ProviderDetails: React.FC = ({ providerType }: ProviderDetailsProps) => { const intl = useIntl(); const { providers, providersError, providersFetchStatus } = useMapToProps(); - const title = intl.formatMessage(messages.ocpClusterDetails); + const title = intl.formatMessage(messages.providerDetails); if (providersError) { return ; @@ -47,10 +47,10 @@ const ClusterDetails: React.FC = () => { ); } - return ; + return ; }; -const useMapToProps = (): ClusterDetailsStateProps => { +const useMapToProps = (): ProviderDetailsStateProps => { // PermissionsWrapper has already made an API request const providersQueryString = getProvidersQuery(providersQuery); const providers = useSelector((state: RootState) => @@ -71,4 +71,4 @@ const useMapToProps = (): ClusterDetailsStateProps => { }; }; -export { ClusterDetails }; +export { ProviderDetails }; diff --git a/src/routes/details/components/providerDetails/clusterDetails/clusterDetailsContent.tsx b/src/routes/details/components/providerDetails/providerDetailsContent.tsx similarity index 59% rename from src/routes/details/components/providerDetails/clusterDetails/clusterDetailsContent.tsx rename to src/routes/details/components/providerDetails/providerDetailsContent.tsx index 94de324e2..1730c91e0 100644 --- a/src/routes/details/components/providerDetails/clusterDetails/clusterDetailsContent.tsx +++ b/src/routes/details/components/providerDetails/providerDetailsContent.tsx @@ -8,30 +8,36 @@ import { useIntl } from 'react-intl'; import { useSelector } from 'react-redux'; import { NotAvailable } from 'routes/components/page/notAvailable'; import { LoadingState } from 'routes/components/state/loadingState'; -import { CloudData } from 'routes/details/components/providerDetails/clusterDetails/components/cloudData'; -import { ClusterData } from 'routes/details/components/providerDetails/clusterDetails/components/clusterData'; -import { CostData } from 'routes/details/components/providerDetails/clusterDetails/components/costData'; import { filterProviders } from 'routes/utils/providers'; import type { RootState } from 'store'; import { FetchStatus } from 'store/common'; import { providersQuery, providersSelectors } from 'store/providers'; -import { styles } from './clusterDetails.styles'; +import { CloudData } from './components/cloudData'; +import { ClusterData } from './components/clusterData'; +import { Finalization } from './components/finalization'; +import { styles } from './providerDetails.styles'; -interface ClusterDetailsContentOwnProps { +interface ProviderDetailsContentOwnProps { clusterId?: string; + providerId?: string; + providerType: ProviderType; } -interface ClusterDetailsContentStateProps { +interface ProviderDetailsContentStateProps { providers: Providers; providersError: AxiosError; providersFetchStatus: FetchStatus; providersQueryString: string; } -type ClusterDetailsContentProps = ClusterDetailsContentOwnProps; +type ProviderDetailsContentProps = ProviderDetailsContentOwnProps; -const ClusterDetailsContent: React.FC = ({ clusterId }: ClusterDetailsContentProps) => { +const ProviderDetailsContent: React.FC = ({ + clusterId, + providerId, + providerType, +}: ProviderDetailsContentProps) => { const intl = useIntl(); const { providers, providersError, providersFetchStatus } = useMapToProps(); @@ -51,20 +57,30 @@ const ClusterDetailsContent: React.FC = ({ clusterId } // Filter OCP providers to skip an extra API request - const ocpProviders = filterProviders(providers, ProviderType.ocp); - const clusterProvider = ocpProviders?.data?.find(val => val.authentication?.credentials?.cluster_id === clusterId); - const cloudProvider = providers?.data?.find(val => val.uuid === clusterProvider?.infrastructure?.uuid); + const filteredProviders = filterProviders(providers, providerType)?.data?.filter(data => data.status !== null); + const provider = filteredProviders?.find( + val => providerId === val.id || (clusterId && val.authentication?.credentials?.cluster_id === clusterId) + ); + if (providerType === ProviderType.ocp) { + const cloudProvider = providers?.data?.find(val => val.uuid === provider?.infrastructure?.uuid); + return ( + <> + + + + + ); + } return ( <> - {cloudProvider && } - {clusterProvider && } - {clusterProvider && } + + ); }; -const useMapToProps = (): ClusterDetailsContentStateProps => { +const useMapToProps = (): ProviderDetailsContentStateProps => { // PermissionsWrapper has already made an API request const providersQueryString = getProvidersQuery(providersQuery); const providers = useSelector((state: RootState) => @@ -85,4 +101,4 @@ const useMapToProps = (): ClusterDetailsContentStateProps => { }; }; -export { ClusterDetailsContent }; +export { ProviderDetailsContent }; diff --git a/src/routes/details/components/providerDetails/clusterDetails/clusterDetailsModal.tsx b/src/routes/details/components/providerDetails/providerDetailsModal.tsx similarity index 61% rename from src/routes/details/components/providerDetails/clusterDetails/clusterDetailsModal.tsx rename to src/routes/details/components/providerDetails/providerDetailsModal.tsx index 334c99a64..aa3765084 100644 --- a/src/routes/details/components/providerDetails/clusterDetails/clusterDetailsModal.tsx +++ b/src/routes/details/components/providerDetails/providerDetailsModal.tsx @@ -1,24 +1,29 @@ import { Button, ButtonVariant } from '@patternfly/react-core'; import { Modal, ModalBody, ModalHeader, ModalVariant } from '@patternfly/react-core/next'; +import type { ProviderType } from 'api/providers'; import messages from 'locales/messages'; import React, { useState } from 'react'; import { useIntl } from 'react-intl'; -import { OverallStatus } from 'routes/details/components/providerDetails/clusterDetails/components/overallStatus'; -import { styles } from './clusterDetails.styles'; -import { ClusterDetailsContent } from './clusterDetailsContent'; +import { OverallStatus } from './components/overallStatus'; +import { styles } from './providerDetails.styles'; +import { ProviderDetailsContent } from './providerDetailsContent'; -interface ClusterDetailsModalOwnProps { +interface ProviderDetailsModalOwnProps { clusterId?: string; showStatus?: boolean; + providerId?: string; + providerType: ProviderType; } -type ClusterDetailsModalProps = ClusterDetailsModalOwnProps; +type ProviderDetailsModalProps = ProviderDetailsModalOwnProps; -const ClusterDetailsModal: React.FC = ({ +const ProviderDetailsModal: React.FC = ({ clusterId, + providerId, + providerType, showStatus = true, -}: ClusterDetailsModalProps) => { +}: ProviderDetailsModalProps) => { const intl = useIntl(); const [isOpen, setIsOpen] = useState(false); @@ -35,18 +40,18 @@ const ClusterDetailsModal: React.FC = ({ return ( <> - {showStatus && } + {showStatus && } - + ); }; -export { ClusterDetailsModal }; +export { ProviderDetailsModal }; diff --git a/src/routes/details/components/providerDetails/clusterDetails/clusterDetailsTable.tsx b/src/routes/details/components/providerDetails/providerDetailsTable.tsx similarity index 53% rename from src/routes/details/components/providerDetails/clusterDetails/clusterDetailsTable.tsx rename to src/routes/details/components/providerDetails/providerDetailsTable.tsx index e642eca7a..8f44e93a1 100644 --- a/src/routes/details/components/providerDetails/clusterDetails/clusterDetailsTable.tsx +++ b/src/routes/details/components/providerDetails/providerDetailsTable.tsx @@ -3,21 +3,20 @@ import messages from 'locales/messages'; import React, { useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; import { DataTable } from 'routes/components/dataTable'; -import { styles } from 'routes/components/dataTable/dataTable.styles'; import { filterProviders } from 'routes/utils/providers'; -import { getReleasePath } from 'utils/paths'; -import { ClusterDetailsModal } from './clusterDetailsModal'; import { OverallStatus } from './components/overallStatus'; +import { SourceLink } from './components/sourceLink'; +import { ProviderDetailsModal } from './providerDetailsModal'; -interface ClusterDetailsTableOwnProps { +interface ProviderDetailsTableOwnProps { providers?: Providers; providerType?: ProviderType; } -type ClusterDetailsTableProps = ClusterDetailsTableOwnProps; +type ProviderDetailsTableProps = ProviderDetailsTableOwnProps; -const ClusterDetailsTable: React.FC = ({ providers, providerType }) => { +const ProviderDetailsTable: React.FC = ({ providers, providerType }) => { const intl = useIntl(); const [columns, setColumns] = useState([]); const [rows, setRows] = useState([]); @@ -28,7 +27,7 @@ const ClusterDetailsTable: React.FC = ({ providers, pr } // Filter OCP providers to skip an extra API request - const filteredProviders = filterProviders(providers, providerType)?.data?.filter(item => item.status !== null); + const filteredProviders = filterProviders(providers, providerType)?.data?.filter(data => data.status !== null); const newRows = []; const newColumns = [ @@ -46,24 +45,15 @@ const ClusterDetailsTable: React.FC = ({ providers, pr }, ]; - const release = getReleasePath(); - - filteredProviders.map(item => { - const clusterId = item?.authentication?.credentials?.cluster_id; + filteredProviders?.map(item => { + // const clusterId = item?.authentication?.credentials?.cluster_id; newRows.push({ cells: [ - { - value: ( - <> - {item.name || clusterId} - {clusterId !== item.name &&
{clusterId}
} - - ), - }, - { value: }, - { value: }, - { value: }, + { value: }, + { value: }, + { value: }, + { value: }, ], item, }); @@ -80,4 +70,4 @@ const ClusterDetailsTable: React.FC = ({ providers, pr return ; }; -export { ClusterDetailsTable }; +export { ProviderDetailsTable }; diff --git a/src/routes/details/components/providerDetails/clusterDetails/utils/format.ts b/src/routes/details/components/providerDetails/utils/format.ts similarity index 100% rename from src/routes/details/components/providerDetails/clusterDetails/utils/format.ts rename to src/routes/details/components/providerDetails/utils/format.ts diff --git a/src/routes/details/components/providerDetails/clusterDetails/utils/icon.tsx b/src/routes/details/components/providerDetails/utils/icon.tsx similarity index 100% rename from src/routes/details/components/providerDetails/clusterDetails/utils/icon.tsx rename to src/routes/details/components/providerDetails/utils/icon.tsx diff --git a/src/routes/details/components/providerDetails/clusterDetails/utils/status.ts b/src/routes/details/components/providerDetails/utils/status.ts similarity index 100% rename from src/routes/details/components/providerDetails/clusterDetails/utils/status.ts rename to src/routes/details/components/providerDetails/utils/status.ts diff --git a/src/routes/details/components/providerDetails/clusterDetails/utils/variant.ts b/src/routes/details/components/providerDetails/utils/variant.ts similarity index 100% rename from src/routes/details/components/providerDetails/clusterDetails/utils/variant.ts rename to src/routes/details/components/providerDetails/utils/variant.ts diff --git a/src/routes/details/gcpDetails/gcpDetails.tsx b/src/routes/details/gcpDetails/gcpDetails.tsx index df05c8249..f10ff25b8 100644 --- a/src/routes/details/gcpDetails/gcpDetails.tsx +++ b/src/routes/details/gcpDetails/gcpDetails.tsx @@ -18,6 +18,7 @@ import { Loading } from 'routes/components/page/loading'; import { NoData } from 'routes/components/page/noData'; import { NoProviders } from 'routes/components/page/noProviders'; import { NotAvailable } from 'routes/components/page/notAvailable'; +import { ProviderDetails } from 'routes/details/components/providerDetails'; import { getIdKeyForGroupBy } from 'routes/utils/computedReport/getComputedGcpReportItems'; import type { ComputedReportItem } from 'routes/utils/computedReport/getComputedReportItems'; import { getUnsortedComputedReportItems } from 'routes/utils/computedReport/getComputedReportItems'; @@ -33,6 +34,7 @@ import { handleOnSort, } from 'routes/utils/queryNavigate'; import { createMapStateToProps, FetchStatus } from 'store/common'; +import { FeatureToggleSelectors } from 'store/featureToggle'; import { providersQuery, providersSelectors } from 'store/providers'; import { reportActions, reportSelectors } from 'store/reports'; import { formatPath } from 'utils/paths'; @@ -48,6 +50,7 @@ import { styles } from './gcpDetails.styles'; interface GcpDetailsStateProps { currency?: string; + isAccountInfoEmptyStateToggleEnabled?: boolean; providers: Providers; providersError: AxiosError; providersFetchStatus: FetchStatus; @@ -320,8 +323,18 @@ class GcpDetails extends React.Component { }; public render() { - const { currency, intl, providers, providersFetchStatus, query, report, reportError, reportFetchStatus, router } = - this.props; + const { + currency, + intl, + isAccountInfoEmptyStateToggleEnabled, + providers, + providersFetchStatus, + query, + report, + reportError, + reportFetchStatus, + router, + } = this.props; const computedItems = this.getComputedItems(); const groupById = getIdKeyForGroupBy(query.group_by); @@ -341,9 +354,17 @@ class GcpDetails extends React.Component { return ; } if (!hasCurrentMonthData(providers)) { - return ; + return ( + : undefined + } + title={title} + /> + ); } } + return (
{ }; public render() { - const { currency, intl, providers, providersFetchStatus, query, report, reportError, reportFetchStatus, router } = - this.props; + const { + currency, + intl, + isAccountInfoEmptyStateToggleEnabled, + providers, + providersFetchStatus, + query, + report, + reportError, + reportFetchStatus, + router, + } = this.props; const computedItems = this.getComputedItems(); const groupById = getIdKeyForGroupBy(query.group_by); @@ -343,9 +356,17 @@ class IbmDetails extends React.Component { return ; } if (!hasCurrentMonthData(providers)) { - return ; + return ( + : undefined + } + title={title} + /> + ); } } + return (
{ const { currency, intl, + isAccountInfoEmptyStateToggleEnabled, providers, providersFetchStatus, query, @@ -352,9 +356,17 @@ class OciDetails extends React.Component { return ; } if (!hasCurrentMonthData(providers)) { - return ; + return ( + : undefined + } + title={title} + /> + ); } } + return (
: undefined, - dataDetailsComponent: groupBy === 'cluster' ? : undefined, + dataDetailsComponent: + groupBy === 'cluster' ? ( + + ) : undefined, costDistribution, costOverviewComponent: ( { if (!hasCurrentMonthData(providers)) { return ( : undefined} + detailsComponent={ + isAccountInfoEmptyStateToggleEnabled ? : undefined + } title={title} /> ); } } + return (
{ }; public render() { - const { currency, intl, providers, providersFetchStatus, query, report, reportError, reportFetchStatus, router } = - this.props; + const { + currency, + intl, + isAccountInfoEmptyStateToggleEnabled, + providers, + providersFetchStatus, + query, + report, + reportError, + reportFetchStatus, + router, + } = this.props; const computedItems = this.getComputedItems(); const groupById = getIdKeyForGroupBy(query.group_by); @@ -399,9 +412,17 @@ class RhelDetails extends React.Component { return ; } if (!hasCurrentMonthData(providers)) { - return ; + return ( + : undefined + } + title={title} + /> + ); } } + return (