diff --git a/packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json b/packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json index 61d779eb9..20724f67e 100644 --- a/packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json +++ b/packages/forklift-console-plugin/locales/en/plugin__forklift-console-plugin.json @@ -62,6 +62,7 @@ "Concern": "Concern", "Concerns": "Concerns", "Conditions": "Conditions", + "Conditions not found": "Conditions not found", "Confirm": "Confirm", "Connection Failed": "Connection Failed", "Controller CPU limit": "Controller CPU limit", @@ -288,6 +289,7 @@ "Password": "Password", "Path": "Path", "Persistent TPM/EFI": "Persistent TPM/EFI", + "Plan details": "Plan details", "Plan name": "Plan name", "Plans": "Plans", "Plans for virtualization": "Plans for virtualization", diff --git a/packages/forklift-console-plugin/src/modules/NetworkMaps/views/details/components/ConditionsSection/ConditionsSection.tsx b/packages/forklift-console-plugin/src/modules/NetworkMaps/views/details/components/ConditionsSection/ConditionsSection.tsx index f03b6647c..d5ef65df6 100644 --- a/packages/forklift-console-plugin/src/modules/NetworkMaps/views/details/components/ConditionsSection/ConditionsSection.tsx +++ b/packages/forklift-console-plugin/src/modules/NetworkMaps/views/details/components/ConditionsSection/ConditionsSection.tsx @@ -3,6 +3,7 @@ import { useForkliftTranslation } from 'src/utils/i18n'; import { K8sResourceCondition } from '@kubev2v/types'; import { Timestamp } from '@openshift-console/dynamic-plugin-sdk'; +import { HelperText, HelperTextItem } from '@patternfly/react-core'; import { TableComposable, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; /** @@ -17,7 +18,11 @@ export const ConditionsSection: React.FC = ({ conditions const { t } = useForkliftTranslation(); if (!conditions) { - return <>; + return ( + + {t('Conditions not found')} + + ); } const getStatusLabel = (status: string) => { diff --git a/packages/forklift-console-plugin/src/modules/NetworkMaps/views/details/components/DetailsSection/components/NetworkMapPageHeadings.tsx b/packages/forklift-console-plugin/src/modules/NetworkMaps/views/details/components/DetailsSection/components/NetworkMapPageHeadings.tsx index 2af00fb55..7d377b481 100644 --- a/packages/forklift-console-plugin/src/modules/NetworkMaps/views/details/components/DetailsSection/components/NetworkMapPageHeadings.tsx +++ b/packages/forklift-console-plugin/src/modules/NetworkMaps/views/details/components/DetailsSection/components/NetworkMapPageHeadings.tsx @@ -46,19 +46,17 @@ export const NetworkMapPageHeadings: React.FC<{ name: string; namespace: string } return ( - <> - } - > - {alerts && alerts.length > 0 && ( - - {alerts} - - )} - - + } + > + {alerts && alerts.length > 0 && ( + + {alerts} + + )} + ); }; diff --git a/packages/forklift-console-plugin/src/modules/NetworkMaps/views/details/components/ProvidersSection/components/ProvidersEdit.tsx b/packages/forklift-console-plugin/src/modules/NetworkMaps/views/details/components/ProvidersSection/components/ProvidersEdit.tsx index d88b7c78c..644ca57b6 100644 --- a/packages/forklift-console-plugin/src/modules/NetworkMaps/views/details/components/ProvidersSection/components/ProvidersEdit.tsx +++ b/packages/forklift-console-plugin/src/modules/NetworkMaps/views/details/components/ProvidersSection/components/ProvidersEdit.tsx @@ -16,14 +16,6 @@ export const ProvidersEdit: React.FC = ({ mode, setMode, }) => { - const ProviderOption = (provider, index) => ( - - ); - const targetProvider = fineProvider({ providers, name: selectedProviderName }); const validated = targetProvider !== undefined ? 'success' : 'error'; @@ -81,6 +73,14 @@ export const ProvidersEdit: React.FC = ({ } }; +const ProviderOption = (provider, index) => ( + +); + export type ProvidersEditProps = { providers: V1beta1Provider[]; selectedProviderName: string; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/PlanDetailsPage.style.css b/packages/forklift-console-plugin/src/modules/Plans/views/details/PlanDetailsPage.style.css index e5e744c88..2fef000bd 100644 --- a/packages/forklift-console-plugin/src/modules/Plans/views/details/PlanDetailsPage.style.css +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/PlanDetailsPage.style.css @@ -25,24 +25,28 @@ } .forklift-page-plan-field-error-validation { - color: var(--pf-c-form__helper-text--m-error--Color); - font-size: small; - padding-top: var(--pf-c-form__helper-text--MarginTop); - } - - .forklift-page-plan-field-warning-validation { - color: var(--pf-c-form__helper-text--m-warning--Color); - font-size: small; - padding-top: var(--pf-c-form__helper-text--MarginTop); - } - - .forklift-page-plan-field-success-validation { - color: var(--pf-c-form__helper-text--m-success--Color); - font-size: small; - padding-top: var(--pf-c-form__helper-text--MarginTop); - } - - .forklift-page-plan-field-default-validation { - font-size: small; - padding-top: var(--pf-c-form__helper-text--MarginTop); - } \ No newline at end of file + color: var(--pf-c-form__helper-text--m-error--Color); + font-size: small; + padding-top: var(--pf-c-form__helper-text--MarginTop); +} + +.forklift-page-plan-field-warning-validation { + color: var(--pf-c-form__helper-text--m-warning--Color); + font-size: small; + padding-top: var(--pf-c-form__helper-text--MarginTop); +} + +.forklift-page-plan-field-success-validation { + color: var(--pf-c-form__helper-text--m-success--Color); + font-size: small; + padding-top: var(--pf-c-form__helper-text--MarginTop); +} + +.forklift-page-plan-field-default-validation { + font-size: small; + padding-top: var(--pf-c-form__helper-text--MarginTop); +} + +.forklift-network-map__details-tab--update-button { + margin-bottom: var(--pf-global--spacer--md); +} \ No newline at end of file diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ConditionsSection/ConditionsSection.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ConditionsSection/ConditionsSection.tsx new file mode 100644 index 000000000..d5ef65df6 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ConditionsSection/ConditionsSection.tsx @@ -0,0 +1,75 @@ +import React from 'react'; +import { useForkliftTranslation } from 'src/utils/i18n'; + +import { K8sResourceCondition } from '@kubev2v/types'; +import { Timestamp } from '@openshift-console/dynamic-plugin-sdk'; +import { HelperText, HelperTextItem } from '@patternfly/react-core'; +import { TableComposable, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; + +/** + * React Component to display a table of conditions. + * + * @component + * @param {ConditionsSectionProps} props - Props for the Conditions component. + * @param {K8sResourceCondition[]} props.conditions - Array of conditions to be displayed. + * @returns {ReactElement} A table displaying the provided conditions. + */ +export const ConditionsSection: React.FC = ({ conditions }) => { + const { t } = useForkliftTranslation(); + + if (!conditions) { + return ( + + {t('Conditions not found')} + + ); + } + + const getStatusLabel = (status: string) => { + switch (status) { + case 'True': + return t('True'); + case 'False': + return t('False'); + default: + return status; + } + }; + + return ( + + + + {t('Type')} + {t('Status')} + {t('Updated')} + {t('Reason')} + {t('Message')} + + + + {conditions.map((condition) => ( + + {condition.type} + {getStatusLabel(condition.status)} + + + + {condition.reason} + {condition?.message || '-'} + + ))} + + + ); +}; + +/** + * Type for the props of the Conditions component. + * + * @typedef {Object} ConditionsProps + * @property {K8sResourceCondition[]} conditions - The conditions to be displayed. + */ +export type ConditionsSectionProps = { + conditions: K8sResourceCondition[]; +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ConditionsSection/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ConditionsSection/index.ts new file mode 100644 index 000000000..75876a3f6 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ConditionsSection/index.ts @@ -0,0 +1,3 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './ConditionsSection'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/DetailsSection.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/DetailsSection.tsx new file mode 100644 index 000000000..599a83dbf --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/DetailsSection.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { ModalHOC } from 'src/modules/Providers/modals'; + +import { V1beta1Plan } from '@kubev2v/types'; +import { DescriptionList } from '@patternfly/react-core'; + +import { + CreatedAtDetailsItem, + NameDetailsItem, + NamespaceDetailsItem, + OwnerDetailsItem, +} from './components'; + +export const DetailsSection: React.FC = (props) => ( + + + +); + +export type DetailsSectionProps = { + obj: V1beta1Plan; +}; + +export const DetailsSectionInternal: React.FC = ({ obj }) => { + return ( + + + + + + + + + + ); +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/CreatedAtDetailsItem.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/CreatedAtDetailsItem.tsx new file mode 100644 index 000000000..68f8f2c65 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/CreatedAtDetailsItem.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { DetailsItem } from 'src/modules/Providers/utils'; +import { useForkliftTranslation } from 'src/utils/i18n'; + +import { Timestamp } from '@openshift-console/dynamic-plugin-sdk'; + +import { PlanDetailsItemProps } from './PlanDetailsItemProps'; + +export const CreatedAtDetailsItem: React.FC = ({ + resource, + moreInfoLink, + helpContent, +}) => { + const { t } = useForkliftTranslation(); + + const defaultMoreInfoLink = 'https://kubernetes.io/docs/reference/using-api/api-concepts'; + const defaultHelpContent = t( + `CreationTimestamp is a timestamp representing the server time when this object was created. + It is not guaranteed to be set in happens-before order across separate operations. + Clients may not set this value. It is represented in RFC3339 form and is in UTC.`, + ); + + return ( + } + moreInfoLink={moreInfoLink ?? defaultMoreInfoLink} + helpContent={helpContent ?? defaultHelpContent} + crumbs={['metadata', 'creationTimestamp']} + /> + ); +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/NameDetailsItem.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/NameDetailsItem.tsx new file mode 100644 index 000000000..d5d10a12b --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/NameDetailsItem.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { DetailsItem } from 'src/modules/Providers/utils'; +import { useForkliftTranslation } from 'src/utils/i18n'; + +import { PlanDetailsItemProps } from './PlanDetailsItemProps'; + +export const NameDetailsItem: React.FC = ({ + resource, + moreInfoLink, + helpContent, +}) => { + const { t } = useForkliftTranslation(); + + const defaultMoreInfoLink = + 'https://kubernetes.io/docs/concepts/overview/working-with-objects/names'; + const defaultHelpContent = t( + 'Name is primarily intended for creation idempotence and configuration definition. Cannot be updated.', + ); + + return ( + + ); +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/NamespaceDetailsItem.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/NamespaceDetailsItem.tsx new file mode 100644 index 000000000..0482c4950 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/NamespaceDetailsItem.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import { DetailsItem } from 'src/modules/Providers/utils'; +import { useForkliftTranslation } from 'src/utils/i18n'; + +import { ResourceLink } from '@openshift-console/dynamic-plugin-sdk'; + +import { PlanDetailsItemProps } from './PlanDetailsItemProps'; + +export const NamespaceDetailsItem: React.FC = ({ + resource, + moreInfoLink, + helpContent, +}) => { + const { t } = useForkliftTranslation(); + + const defaultMoreInfoLink = + 'https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces'; + const defaultHelpContent = t( + `Namespace defines the space within which each name must be unique. + An empty namespace is equivalent to the "default" namespace, but "default" is the canonical representation. + Not all objects are required to be scoped to a namespace - + the value of this field for those objects will be empty.`, + ); + + return ( + + } + moreInfoLink={moreInfoLink ?? defaultMoreInfoLink} + helpContent={helpContent ?? defaultHelpContent} + crumbs={['metadata', 'namespace']} + /> + ); +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/OwnerDetailsItem.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/OwnerDetailsItem.tsx new file mode 100644 index 000000000..92181621b --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/OwnerDetailsItem.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import { DetailsItem, OwnerReferencesItem } from 'src/modules/Providers/utils'; +import { useForkliftTranslation } from 'src/utils/i18n'; + +import { PlanDetailsItemProps } from './PlanDetailsItemProps'; + +export const OwnerDetailsItem: React.FC = ({ + resource, + moreInfoLink, + helpContent, +}) => { + const { t } = useForkliftTranslation(); + + const defaultMoreInfoLink = + 'https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/'; + const defaultHelpContent = t( + `List of objects depended by this object. If ALL objects in the list have been deleted, + this object will be garbage collected. If this object is managed by a controller, + then an entry in this list will point to this controller, with the controller field set to true. + There cannot be more than one managing controller.`, + ); + + return ( + } + moreInfoLink={moreInfoLink ?? defaultMoreInfoLink} + helpContent={helpContent ?? defaultHelpContent} + crumbs={['metadata', 'ownerReferences']} + /> + ); +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/PlanDetailsItemProps.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/PlanDetailsItemProps.tsx new file mode 100644 index 000000000..4fd2c3e4e --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/PlanDetailsItemProps.tsx @@ -0,0 +1,10 @@ +import { ReactNode } from 'react'; + +import { V1beta1Plan } from '@kubev2v/types'; + +export interface PlanDetailsItemProps { + resource: V1beta1Plan; + canPatch?: boolean; + moreInfoLink?: string; + helpContent?: ReactNode; +} diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/index.ts new file mode 100644 index 000000000..c66150722 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/components/index.ts @@ -0,0 +1,7 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './CreatedAtDetailsItem'; +export * from './NameDetailsItem'; +export * from './NamespaceDetailsItem'; +export * from './OwnerDetailsItem'; +export * from './PlanDetailsItemProps'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/index.ts new file mode 100644 index 000000000..86a1ade75 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/DetailsSection/index.ts @@ -0,0 +1,4 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './components'; +export * from './DetailsSection'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/ProvidersSection.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/ProvidersSection.tsx new file mode 100644 index 000000000..cdb942572 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/ProvidersSection.tsx @@ -0,0 +1,118 @@ +import React, { useReducer } from 'react'; +import { Suspend } from 'src/modules/Plans/views/details/components'; +import { useForkliftTranslation } from 'src/utils/i18n'; + +import { + PlanModel, + ProviderModelGroupVersionKind, + V1beta1Plan, + V1beta1Provider, +} from '@kubev2v/types'; +import { k8sUpdate, useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk'; +import { Button, DescriptionList, Flex, FlexItem, Spinner } from '@patternfly/react-core'; + +import { ProvidersEdit } from './components'; +import { providersSectionReducer, ProvidersSectionState } from './state'; + +const initialState: ProvidersSectionState = { + plan: null, + sourceProviderMode: 'view', + targetProviderMode: 'view', + hasChanges: false, + updating: false, +}; + +export const ProvidersSection: React.FC = ({ obj }) => { + const { t } = useForkliftTranslation(); + const [state, dispatch] = useReducer(providersSectionReducer, initialState); + + // Initialize the state with the prop obj + React.useEffect(() => { + dispatch({ type: 'INIT', payload: obj }); + }, [obj]); + + const [providers, providersLoaded, providersLoadError] = useK8sWatchResource({ + groupVersionKind: ProviderModelGroupVersionKind, + namespaced: true, + isList: true, + namespace: obj.metadata.namespace, + }); + + const targetProviders = providers.filter((p) => ['openshift'].includes(p?.spec?.type)); + + const onUpdate = async () => { + dispatch({ type: 'SET_UPDATING', payload: true }); + await k8sUpdate({ model: PlanModel, data: state.plan }); + }; + + return ( + + + + + + + + + + + + + + dispatch({ + type: 'SET_SOURCE_PROVIDER', + payload: providers.find((p) => p?.metadata?.name === value), + }) + } + invalidLabel={t('The chosen provider is no longer available.')} + mode={state.sourceProviderMode} + helpContent="source provider" + setMode={() => dispatch({ type: 'SET_SOURCE_PROVIDER_MODE', payload: 'edit' })} + /> + + + dispatch({ + type: 'SET_TARGET_PROVIDER', + payload: providers.find((p) => p?.metadata?.name === value), + }) + } + invalidLabel={t('The chosen provider is no longer available.')} + mode={state.targetProviderMode} + helpContent="Target provider" + setMode={() => dispatch({ type: 'SET_TARGET_PROVIDER_MODE', payload: 'edit' })} + /> + + + ); +}; + +export type ProvidersSectionProps = { + obj: V1beta1Plan; +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/components/ProvidersEdit.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/components/ProvidersEdit.tsx new file mode 100644 index 000000000..644ca57b6 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/components/ProvidersEdit.tsx @@ -0,0 +1,102 @@ +import React, { ReactNode } from 'react'; +import { DetailsItem } from 'src/modules/Providers/utils'; + +import { ProviderModelGroupVersionKind, V1beta1Provider } from '@kubev2v/types'; +import { ResourceLink } from '@openshift-console/dynamic-plugin-sdk'; +import { Form, FormGroup, FormSelect, FormSelectOption } from '@patternfly/react-core'; + +export const ProvidersEdit: React.FC = ({ + providers, + selectedProviderName, + onChange, + label, + placeHolderLabel, + invalidLabel, + helpContent, + mode, + setMode, +}) => { + const targetProvider = fineProvider({ providers, name: selectedProviderName }); + + const validated = targetProvider !== undefined ? 'success' : 'error'; + const hasProviders = providers?.length > 0; + + if (mode === 'edit') { + return ( +
+ + + {[ + , + ...providers.map(ProviderOption), + ]} + + +
+ ); + } else { + return ( + + } + onEdit={hasProviders ? () => setMode('edit') : undefined} + helpContent={helpContent} + crumbs={['spec', 'providers']} + /> + ); + } +}; + +const ProviderOption = (provider, index) => ( + +); + +export type ProvidersEditProps = { + providers: V1beta1Provider[]; + selectedProviderName: string; + onChange: (value: string) => void; + label: string; + placeHolderLabel: string; + invalidLabel: string; + helpContent: ReactNode; + mode: 'edit' | 'view'; + setMode: (mode: 'edit' | 'view') => void; +}; + +type FindProviderFunction = (args: { + providers: V1beta1Provider[]; + name: string; +}) => V1beta1Provider; + +const fineProvider: FindProviderFunction = ({ providers, name }) => + providers.find((p) => p.metadata.name === name); diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/components/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/components/index.ts new file mode 100644 index 000000000..a64b2a035 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/components/index.ts @@ -0,0 +1,3 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './ProvidersEdit'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/index.ts new file mode 100644 index 000000000..ed872e101 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/index.ts @@ -0,0 +1,5 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './components'; +export * from './ProvidersSection'; +export * from './state'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/state/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/state/index.ts new file mode 100644 index 000000000..d79f304c6 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/state/index.ts @@ -0,0 +1,3 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './reducer'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/state/reducer.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/state/reducer.ts new file mode 100644 index 000000000..93b37d3a8 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/ProvidersSection/state/reducer.ts @@ -0,0 +1,66 @@ +import { deepCopy } from 'src/modules/NetworkMaps/utils'; + +import { V1beta1Plan, V1beta1Provider } from '@kubev2v/types'; + +export interface ProvidersSectionState { + plan: V1beta1Plan | null; + sourceProviderMode: 'view' | 'edit'; + targetProviderMode: 'view' | 'edit'; + hasChanges: boolean; + updating: boolean; +} + +export type ProvidersAction = + | { type: 'SET_SOURCE_PROVIDER'; payload: V1beta1Provider } + | { type: 'SET_TARGET_PROVIDER'; payload: V1beta1Provider } + | { type: 'SET_SOURCE_PROVIDER_MODE'; payload: 'view' | 'edit' } + | { type: 'SET_TARGET_PROVIDER_MODE'; payload: 'view' | 'edit' } + | { type: 'SET_UPDATING'; payload: boolean } + | { type: 'INIT'; payload: V1beta1Plan }; + +export function providersSectionReducer( + state: ProvidersSectionState, + action: ProvidersAction, +): ProvidersSectionState { + let newState: ProvidersSectionState; + + switch (action.type) { + case 'SET_SOURCE_PROVIDER': + newState = { ...state, hasChanges: true }; + newState.plan.spec.provider.source = { + apiVersion: action.payload?.apiVersion, + kind: action.payload?.kind, + name: action.payload?.metadata?.name, + namespace: action.payload?.metadata?.namespace, + uid: action.payload?.metadata?.uid, + }; + return newState; + case 'SET_TARGET_PROVIDER': + newState = { ...state, hasChanges: true }; + newState.plan.spec.provider.destination = { + apiVersion: action.payload?.apiVersion, + kind: action.payload?.kind, + name: action.payload?.metadata?.name, + namespace: action.payload?.metadata?.namespace, + uid: action.payload?.metadata?.uid, + }; + return newState; + case 'SET_SOURCE_PROVIDER_MODE': + return { ...state, sourceProviderMode: action.payload }; + case 'SET_TARGET_PROVIDER_MODE': + return { ...state, targetProviderMode: action.payload }; + + case 'SET_UPDATING': + return { ...state, updating: action.payload }; + case 'INIT': + return { + plan: deepCopy(action.payload), + targetProviderMode: 'view', + sourceProviderMode: 'view', + hasChanges: false, + updating: false, + }; + default: + return state; + } +} diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/index.ts index da24be5e1..460e0dc5e 100644 --- a/packages/forklift-console-plugin/src/modules/Plans/views/details/components/index.ts +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/components/index.ts @@ -1,4 +1,7 @@ // @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './ConditionsSection'; +export * from './DetailsSection'; export * from './Loading'; +export * from './ProvidersSection'; export * from './Suspend'; // @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/Details/PlanDetails.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/Details/PlanDetails.tsx index fa0821f71..eea50c982 100644 --- a/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/Details/PlanDetails.tsx +++ b/packages/forklift-console-plugin/src/modules/Plans/views/details/tabs/Details/PlanDetails.tsx @@ -1,16 +1,31 @@ import React from 'react'; +import SectionHeading from 'src/components/headers/SectionHeading'; import { useForkliftTranslation } from 'src/utils/i18n'; -import { PageSection, Title } from '@patternfly/react-core'; +import { PageSection } from '@patternfly/react-core'; +import { ConditionsSection, DetailsSection, ProvidersSection, Suspend } from '../../components'; import { PlanDetailsTabProps } from '../../PlanDetailsPage'; export const PlanDetails: React.FC = ({ plan, loaded, loadError }) => { const { t } = useForkliftTranslation(); return ( - - {t('Details')} - + + + + + + + + + + + + + + + + ); }; diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/details/components/ConditionsSection/ConditionsSection.tsx b/packages/forklift-console-plugin/src/modules/Providers/views/details/components/ConditionsSection/ConditionsSection.tsx index c69cd3156..520c842a8 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/details/components/ConditionsSection/ConditionsSection.tsx +++ b/packages/forklift-console-plugin/src/modules/Providers/views/details/components/ConditionsSection/ConditionsSection.tsx @@ -3,6 +3,7 @@ import { useForkliftTranslation } from 'src/utils/i18n'; import { K8sResourceCondition } from '@kubev2v/types'; import { Timestamp } from '@openshift-console/dynamic-plugin-sdk'; +import { HelperText, HelperTextItem } from '@patternfly/react-core'; import { TableComposable, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; /** @@ -17,7 +18,11 @@ export const ConditionsSection: React.FC = ({ conditions }) => const { t } = useForkliftTranslation(); if (!conditions) { - return <>; + return ( + + {t('Conditions not found')} + + ); } const getStatusLabel = (status: string) => { diff --git a/packages/forklift-console-plugin/src/modules/StorageMaps/views/details/components/ConditionsSection/ConditionsSection.tsx b/packages/forklift-console-plugin/src/modules/StorageMaps/views/details/components/ConditionsSection/ConditionsSection.tsx index f03b6647c..d5ef65df6 100644 --- a/packages/forklift-console-plugin/src/modules/StorageMaps/views/details/components/ConditionsSection/ConditionsSection.tsx +++ b/packages/forklift-console-plugin/src/modules/StorageMaps/views/details/components/ConditionsSection/ConditionsSection.tsx @@ -3,6 +3,7 @@ import { useForkliftTranslation } from 'src/utils/i18n'; import { K8sResourceCondition } from '@kubev2v/types'; import { Timestamp } from '@openshift-console/dynamic-plugin-sdk'; +import { HelperText, HelperTextItem } from '@patternfly/react-core'; import { TableComposable, Tbody, Td, Th, Thead, Tr } from '@patternfly/react-table'; /** @@ -17,7 +18,11 @@ export const ConditionsSection: React.FC = ({ conditions const { t } = useForkliftTranslation(); if (!conditions) { - return <>; + return ( + + {t('Conditions not found')} + + ); } const getStatusLabel = (status: string) => {