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 9a1c59602..9fb4f9dda 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 @@ -69,7 +69,6 @@ "Create NetworkMap": "Create NetworkMap", "Create new provider": "Create new provider", "Create plan": "Create plan", - "Create Plan": "Create Plan", "Create provider": "Create provider", "Create Provider": "Create Provider", "Create Providers by using the form or manually entering YAML or JSON definitions. Provider CRs store attributes that enable MTV to connect to and interact with the source and target providers.": "Create Providers by using the form or manually entering YAML or JSON definitions. Provider CRs store attributes that enable MTV to connect to and interact with the source and target providers.", @@ -171,6 +170,7 @@ "Filter by status": "Filter by status", "Filter by template": "Filter by template", "Filter by tenant": "Filter by tenant", + "Filter provider": "Filter provider", "Flavor": "Flavor", "For example: <1>https://identity_service.com:5000/v3.": "For example: <1>https://identity_service.com:5000/v3.", "From": "From", @@ -345,6 +345,8 @@ "Secrets": "Secrets", "Select migration network": "Select migration network", "Select provider type": "Select provider type", + "Select source provider": "Select source provider", + "Select virtual machines": "Select virtual machines", "Select virtual machines and create a migration plan.": "Select virtual machines and create a migration plan.", "Selected columns will be displayed in the table.": "Selected columns will be displayed in the table.", "Selected VMs": "Selected VMs", @@ -403,12 +405,14 @@ "This plan cannot be edited because it is running must gather.": "This plan cannot be edited because it is running must gather.", "This plan cannot be edited because the inventory data for its associated providers is not ready.": "This plan cannot be edited because the inventory data for its associated providers is not ready.", "This plan cannot be restarted because it is running must gather service": "This plan cannot be restarted because it is running must gather service", + "This plan will be created in <1>{defaultNamespace} namespace, if you wish to choose another namespace please cancel, and choose a namespace from the top bar.": "This plan will be created in <1>{defaultNamespace} namespace, if you wish to choose another namespace please cancel, and choose a namespace from the top bar.", "This provider will be created in <1>{defaultNamespace} namespace, if you wish to choose another namespace please cancel, and choose a namespace from the top bar.": "This provider will be created in <1>{defaultNamespace} namespace, if you wish to choose another namespace please cancel, and choose a namespace from the top bar.", "This resource is managed by <2> and any modifications may be overwritten. Edit the managing resource to preserve changes.": "This resource is managed by <2> and any modifications may be overwritten. Edit the managing resource to preserve changes.", "To": "To", "To make changes to the plan, select Duplicate and edit the duplicate plan.": "To make changes to the plan, select Duplicate and edit the duplicate plan.", - "To migrate virtual machines from <1>{name} provider, select the virtual machines to migrate from the list of available virtual machines and click the <4>Migrate button.": "To migrate virtual machines from <1>{name} provider, select the virtual machines to migrate from the list of available virtual machines and click the <4>Migrate button.", + "To migrate virtual machines from <1>{name} provider, select the virtual machines to migrate from the list of available virtual machines and click the <4>Create migration plan button.": "To migrate virtual machines from <1>{name} provider, select the virtual machines to migrate from the list of available virtual machines and click the <4>Create migration plan button.", "To migrate virtual machines from <1>{provider.metadata.name} provider, select the virtual machines to migrate from the list of available virtual machines located in the virtual machines tab. <4>Go to <1>Virtual Machines tab": "To migrate virtual machines from <1>{provider.metadata.name} provider, select the virtual machines to migrate from the list of available virtual machines located in the virtual machines tab. <4>Go to <1>Virtual Machines tab", + "To migrate virtual machines select a provider, then select the virtual machines to migrate and click the <1>Create migration plan button.": "To migrate virtual machines select a provider, then select the virtual machines to migrate and click the <1>Create migration plan button.", "To troubleshoot, check the Forklift controller pod events and logs.": "To troubleshoot, check the Forklift controller pod events and logs.", "To troubleshoot, check the Forklift controller pod logs.": "To troubleshoot, check the Forklift controller pod logs.", "To troubleshoot, view the provider status available in the provider details page\n and check the Forklift controller pod logs.": "To troubleshoot, view the provider status available in the provider details page\n and check the Forklift controller pod logs.", diff --git a/packages/forklift-console-plugin/src/components/images/logos.tsx b/packages/forklift-console-plugin/src/components/images/logos.tsx new file mode 100644 index 000000000..08da11474 --- /dev/null +++ b/packages/forklift-console-plugin/src/components/images/logos.tsx @@ -0,0 +1,52 @@ +import React from 'react'; + +import openshiftImg from './resources/openshift.svg'; +import openstackImg from './resources/openstack.svg'; +import ovaImg from './resources/ova.svg'; +import redhatImg from './resources/redhat.svg'; +import vmImg from './resources/vm.svg'; + +export const openshiftLogo = ( + PatternFly logo +); + +export const openstackLogo = ( + PatternFly logo +); + +export const vmLogo = ( + PatternFly logo +); + +export const redhatLogo = ( + PatternFly logo +); + +export const ovaLogo = ( + PatternFly logo +); diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/create/images/openshift.svg b/packages/forklift-console-plugin/src/components/images/resources/openshift.svg similarity index 95% rename from packages/forklift-console-plugin/src/modules/Providers/views/create/images/openshift.svg rename to packages/forklift-console-plugin/src/components/images/resources/openshift.svg index 5bc707b41..20a1577de 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/create/images/openshift.svg +++ b/packages/forklift-console-plugin/src/components/images/resources/openshift.svg @@ -8,7 +8,7 @@ viewBox="-1.7338671 -1.7338671 59.64439 59.616873" id="svg45453" sodipodi:docname="openshift.svg" - inkscape:version="1.2.2 (b0a8486541, 2022-12-01)" + inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" @@ -24,19 +24,19 @@ inkscape:deskcolor="#d1d1d1" showgrid="false" inkscape:zoom="1.3372396" - inkscape:cx="195.17819" - inkscape:cy="383.6261" + inkscape:cx="195.926" + inkscape:cy="384" inkscape:window-width="3440" inkscape:window-height="1371" inkscape:window-x="0" - inkscape:window-y="0" + inkscape:window-y="32" inkscape:window-maximized="1" inkscape:current-layer="svg45453" /> + transform="translate(-0.41875627,-1.6449201)"> + + + + + + + + + diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/create/images/ova.svg b/packages/forklift-console-plugin/src/components/images/resources/ova.svg similarity index 58% rename from packages/forklift-console-plugin/src/modules/Providers/views/create/images/ova.svg rename to packages/forklift-console-plugin/src/components/images/resources/ova.svg index 21334cd74..1fe9a71e1 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/create/images/ova.svg +++ b/packages/forklift-console-plugin/src/components/images/resources/ova.svg @@ -1,13 +1,13 @@ diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/create/images/redhat.svg b/packages/forklift-console-plugin/src/components/images/resources/redhat.svg similarity index 100% rename from packages/forklift-console-plugin/src/modules/Providers/views/create/images/redhat.svg rename to packages/forklift-console-plugin/src/components/images/resources/redhat.svg diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/create/images/vm.svg b/packages/forklift-console-plugin/src/components/images/resources/vm.svg similarity index 50% rename from packages/forklift-console-plugin/src/modules/Providers/views/create/images/vm.svg rename to packages/forklift-console-plugin/src/components/images/resources/vm.svg index 3152e0841..069f8f02c 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/create/images/vm.svg +++ b/packages/forklift-console-plugin/src/components/images/resources/vm.svg @@ -9,7 +9,7 @@ id="icon" version="1.1" sodipodi:docname="vm.svg" - inkscape:version="1.2.2 (b0a8486541, 2022-12-01)" + inkscape:version="1.3.2 (091e20ef0f, 2023-11-25)" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" @@ -24,14 +24,14 @@ inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" showgrid="false" - inkscape:zoom="1.28375" - inkscape:cx="400.77897" - inkscape:cy="399.61052" - inkscape:window-width="3440" - inkscape:window-height="1371" - inkscape:window-x="0" - inkscape:window-y="0" - inkscape:window-maximized="1" + inkscape:zoom="0.90774833" + inkscape:cx="445.05728" + inkscape:cy="421.3723" + inkscape:window-width="1499" + inkscape:window-height="1243" + inkscape:window-x="1740" + inkscape:window-y="119" + inkscape:window-maximized="0" inkscape:current-layer="icon" /> @@ -43,7 +43,7 @@ , + + { + type: 'console.resource/create', + properties: { + component: { + $codeRef: 'PlanCreatePage', + }, + model: PlanModelGroupVersionKind, + ...PlanModel, + }, + } as EncodedExtension, ]; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/PlanCreatePage.style.css b/packages/forklift-console-plugin/src/modules/Plans/views/create/PlanCreatePage.style.css new file mode 100644 index 000000000..3ffbbcddd --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/PlanCreatePage.style.css @@ -0,0 +1,64 @@ +.forklift-create-provider-edit-section { + padding-top: 0; +} + +.forklift-create-provider-edit-section-header { + margin-bottom: 0; +} + +.forklift-section-create-deviser { + padding-top: var(--pf-global--spacer--md); + padding-bottom: var(--pf-global--spacer--md); +} + +.forklift-create-subtitle { + padding-bottom: var(--pf-global--spacer--md); +} + +.forklift-create-card--list { + list-style-type: none; + padding: 0; +} + +.forklift--create-provider-edit-card-selected { + min-width: 25%; +} + +.forklift--create-provider-edit-card-title { + justify-content: normal; +} + +.forklift--create-provider-edit-card-title-logo { + margin-right: var(--pf-global--spacer--sm); +} + +.forklift--create-provider-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--create-provider-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--create-provider-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--create-provider-field-default-validation { + font-size: small; + padding-top: var(--pf-c-form__helper-text--MarginTop); +} + +.forklift--create-plan--filters-toolbar { + padding-bottom: 0; +} + +.forklift--create-plan--alert { + margin-top: var(--pf-global--spacer--md); +} diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/PlanCreatePage.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/create/PlanCreatePage.tsx new file mode 100644 index 000000000..87f7e016e --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/PlanCreatePage.tsx @@ -0,0 +1,138 @@ +import React, { useReducer } from 'react'; +import { Trans } from 'react-i18next'; +import { useHistory } from 'react-router'; +import { getResourceUrl } from 'src/modules/Providers/utils'; +import { MigrationAction } from 'src/modules/Providers/views/details/tabs/VirtualMachines/components/MigrationAction'; +import { useForkliftTranslation } from 'src/utils/i18n'; + +import { ProviderModelGroupVersionKind, ProviderModelRef, V1beta1Provider } from '@kubev2v/types'; +import { useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk'; +import { + Alert, + Button, + PageSection, + Title, + Toolbar, + ToolbarContent, + ToolbarItem, +} from '@patternfly/react-core'; +import BellIcon from '@patternfly/react-icons/dist/esm/icons/bell-icon'; + +import { findProviderByID, PlanCreateForm, ProviderVirtualMachinesList } from './components'; +import { planCreatePageInitialState, planCreatePageReducer } from './states'; + +import './PlanCreatePage.style.css'; + +export const PlanCreatePage: React.FC<{ + namespace: string; +}> = ({ namespace }) => { + const { t } = useForkliftTranslation(); + const history = useHistory(); + const [filterState, filterDispatch] = useReducer( + planCreatePageReducer, + planCreatePageInitialState, + ); + + const [providers] = useK8sWatchResource({ + groupVersionKind: ProviderModelGroupVersionKind, + namespaced: true, + isList: true, + namespace, + }); + + const defaultNamespace = process?.env?.DEFAULT_NAMESPACE || 'default'; + + const providersListURL = getResourceUrl({ + reference: ProviderModelRef, + namespace: namespace, + }); + + const filteredProviders = providers.filter( + (provider) => + provider.metadata.name.toLowerCase().includes(filterState.nameFilter.toLowerCase()) && + (filterState.typeFilters.length === 0 || + filterState.typeFilters.includes(provider.spec.type)), + ); + + const selectedProvider = + filterState.selectedProviderUID !== '' + ? findProviderByID(filterState.selectedProviderUID, providers) + : undefined; + const selectedProviderName = selectedProvider?.metadata?.name; + const selectedProviderNamespace = selectedProvider?.metadata?.namespace; + + return ( +
+ + } + variant="info" + title={t('How to create a migration plan')} + > + + To migrate virtual machines select a provider, then select the virtual machines to + migrate and click the Create migration plan button. + + + + {!namespace && ( + + + This plan will be created in {defaultNamespace} namespace, if you + wish to choose another namespace please cancel, and choose a namespace from the top + bar. + + + )} + + + {t('Select source provider')} + + + + + {filterState.selectedProviderUID && ( + + filterDispatch({ type: 'UPDATE_SELECTED_VMS', payload: selectedVms }) + } + initialSelectedIds={filterState.selectedVMs.map((vm) => vm.vm.id)} + /> + )} + + + + + + + + + + + + +
+ ); +}; + +export default PlanCreatePage; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/components/ChipsToolbarProviders.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/ChipsToolbarProviders.tsx new file mode 100644 index 000000000..25837d3c2 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/ChipsToolbarProviders.tsx @@ -0,0 +1,60 @@ +import React from 'react'; + +import { Chip, ChipGroup, Toolbar, ToolbarContent, ToolbarItem } from '@patternfly/react-core'; + +import { PlanCreatePageState } from '../states'; + +export interface ChipsToolbarProvidersProps { + filterState: PlanCreatePageState; + filterDispatch: React.Dispatch<{ + type: string; + payload?: string | string[]; + }>; +} + +export const ChipsToolbarProviders: React.FunctionComponent = ({ + filterState, + filterDispatch, +}) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const deleteNameFilter = (_) => { + filterDispatch({ type: 'SET_NAME_FILTER', payload: '' }); + }; + + const deleteTypeFilter = (type: string) => { + filterDispatch({ + type: 'UPDATE_TYPE_FILTERS', + payload: filterState.typeFilters.filter((t) => t !== type), + }); + }; + + const name = filterState.nameFilter; + const types = filterState.typeFilters; + + return ( + + + {name && ( + + + deleteNameFilter(name)}> + {name} + + + + )} + {types && types.length > 0 && ( + + + {types.map((type, index) => ( + deleteTypeFilter(type)}> + {type} + + ))} + + + )} + + + ); +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/components/FiltersToolbarProviders.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/FiltersToolbarProviders.tsx new file mode 100644 index 000000000..13652b61e --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/FiltersToolbarProviders.tsx @@ -0,0 +1,38 @@ +import React from 'react'; + +import { Toolbar, ToolbarContent, ToolbarItem } from '@patternfly/react-core'; + +import { PlanCreatePageState } from '../states'; + +import SearchInputProvider from './SearchInputProvider'; +import SelectProvider from './SelectProvider'; + +export interface FiltersToolbarProvidersProps { + filterState: PlanCreatePageState; + filterDispatch: React.Dispatch<{ + type: string; + payload?: string | string[]; + }>; + className?: string; +} + +export const FiltersToolbarProviders: React.FunctionComponent = ({ + filterState, + filterDispatch, + className, +}) => { + return ( + + + <> + + + + + + + + + + ); +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/components/PlanCreateForm.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/PlanCreateForm.tsx new file mode 100644 index 000000000..34a0d940a --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/PlanCreateForm.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { SelectableGallery } from 'src/modules/Providers/utils/components/Galerry/SelectableGallery'; +import { VmData } from 'src/modules/Providers/views'; + +import { V1beta1Provider } from '@kubev2v/types'; +import { Form, FormGroup } from '@patternfly/react-core'; + +import { PlanCreatePageState } from '../states'; + +import { ChipsToolbarProviders } from './ChipsToolbarProviders'; +import { createProviderCardItems } from './createProviderCardItems'; +import { FiltersToolbarProviders } from './FiltersToolbarProviders'; + +export type PlanCreateFormProps = { + providers: V1beta1Provider[]; + filterState: PlanCreatePageState; + filterDispatch: React.Dispatch<{ + type: string; + payload?: string | string[] | VmData[]; + }>; +}; + +/** + * PlanCreateForm component is responsible for rendering the form to create a migration plan. + * It allows users to select a source provider from a gallery of available providers. + */ +export const PlanCreateForm: React.FC = ({ + providers, + filterState, + filterDispatch, +}) => { + const providerCardItems = createProviderCardItems(providers); + + const onChange = (id: string) => { + filterDispatch({ type: 'SELECT_PROVIDER', payload: id || '' }); + }; + + return ( +
+
+ + + + + + +
+
+ ); +}; + +export default PlanCreateForm; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/components/ProviderCardContent.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/ProviderCardContent.tsx new file mode 100644 index 000000000..47b03cedc --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/ProviderCardContent.tsx @@ -0,0 +1,32 @@ +import React from 'react'; + +import { V1beta1Provider } from '@kubev2v/types'; + +export const ProviderCardContent: React.FC = ({ + provider, + typeLabel, +}) => { + return ( +
    +
  • + Name: {provider.metadata.name} +
  • +
  • + Namespace: {provider.metadata.namespace} +
  • + {typeLabel && ( +
  • + Type: {typeLabel} +
  • + )} +
  • + Phase: {provider.status.phase} +
  • +
+ ); +}; + +export type ProviderCardContentProps = { + provider: V1beta1Provider; + typeLabel?: string; +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/components/ProviderCardItems.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/ProviderCardItems.tsx new file mode 100644 index 000000000..2a065b6a9 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/ProviderCardItems.tsx @@ -0,0 +1,36 @@ +import { + openshiftLogo, + openstackLogo, + ovaLogo, + redhatLogo, + vmLogo, +} from 'src/components/images/logos'; +import { SelectableGalleryItem } from 'src/modules/Providers/utils/components/Galerry/SelectableGallery'; + +export const providerCardItems: Record = { + vsphere: { + title: 'vSphere', + logo: vmLogo, + content: "vSphere is VMware's cloud computing virtualization platform.", + }, + ovirt: { + title: 'Red Hat Virtualization', + logo: redhatLogo, + content: 'Red Hat Virtualization (RHV) is a virtualization platform from Red Hat.', + }, + openstack: { + title: 'OpenStack', + logo: openstackLogo, + content: 'OpenStack is a cloud computing platform that controls large pools of resources.', + }, + ova: { + title: 'Open Virtual Appliance (OVA)', + logo: ovaLogo, + content: 'OVA file is a virtual appliance used by virtualization applications.', + }, + openshift: { + title: 'OpenShift Virtualization', + logo: openshiftLogo, + content: 'OpenShift Virtualization run and manage virtual machine in OpenShift.', + }, +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/components/ProvidersVirtualMachinesList.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/ProvidersVirtualMachinesList.tsx new file mode 100644 index 000000000..8911df119 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/ProvidersVirtualMachinesList.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { useProviderInventory } from 'src/modules/Providers/hooks'; +import { ProviderVirtualMachinesListWrapper, VmData } from 'src/modules/Providers/views'; + +import { ProviderInventory, ProviderModelGroupVersionKind, V1beta1Provider } from '@kubev2v/types'; +import { useK8sWatchResource } from '@openshift-console/dynamic-plugin-sdk'; + +export const ProviderVirtualMachinesList: React.FC<{ + title: string; + name: string; + namespace: string; + onSelect?: (selectedIds: VmData[]) => void; + initialSelectedIds?: string[]; +}> = ({ title, name, namespace, onSelect, initialSelectedIds }) => { + const [provider, providerLoaded, providerLoadError] = useK8sWatchResource({ + groupVersionKind: ProviderModelGroupVersionKind, + namespaced: true, + name, + namespace, + }); + + const { inventory } = useProviderInventory({ provider }); + const obj = { provider, inventory }; + + return ( + + ); +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/components/SearchInputProvider.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/SearchInputProvider.tsx new file mode 100644 index 000000000..29f083c0e --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/SearchInputProvider.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { useForkliftTranslation } from 'src/utils/i18n'; + +import { SearchInput } from '@patternfly/react-core'; + +import { PlanCreatePageState } from '../states'; + +export interface SearchInputProviderProps { + filterState: PlanCreatePageState; + filterDispatch: React.Dispatch<{ + type: string; + payload?: string | string[]; + }>; +} + +export const SearchInputProvider: React.FunctionComponent = ({ + filterState, + filterDispatch, +}) => { + const { t } = useForkliftTranslation(); + + const updateNameFilter = (value: string) => { + filterDispatch({ type: 'SET_NAME_FILTER', payload: value }); + }; + + return ( +
+ updateNameFilter(value)} + onClear={() => updateNameFilter('')} + /> +
+ ); +}; + +export default SearchInputProvider; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/components/SelectProvider.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/SelectProvider.tsx new file mode 100644 index 000000000..0e7ff0487 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/SelectProvider.tsx @@ -0,0 +1,71 @@ +import React, { useState } from 'react'; +import { useForkliftTranslation } from 'src/utils/i18n'; + +import { Select, SelectOption, SelectVariant } from '@patternfly/react-core'; +import FilterIcon from '@patternfly/react-icons/dist/esm/icons/filter-icon'; + +import providerTypes from '../constanats/providerTypes'; +import { PlanCreatePageState } from '../states'; + +export interface SelectProviderProps { + filterState: PlanCreatePageState; + filterDispatch: React.Dispatch<{ + type: string; + payload?: string | string[]; + }>; +} + +export const SelectProvider: React.FunctionComponent = ({ + filterState, + filterDispatch, +}) => { + const { t } = useForkliftTranslation(); + const [isOpen, setIsOpen] = useState(false); + + const onToggle = () => { + setIsOpen(!isOpen); + }; + + const providerTypesArray = Object.keys(providerTypes); + + const onSelect = (_, selection: string) => { + const prevTypeFilters = filterState.typeFilters; + const typeFilters = prevTypeFilters.includes(selection) + ? prevTypeFilters.filter((item: string) => item !== selection) + : [...prevTypeFilters, selection]; + filterDispatch({ type: 'UPDATE_TYPE_FILTERS', payload: typeFilters }); + }; + + const renderOptions = () => { + return providerTypesArray.map((providerType, index) => ( + + )); + }; + + return ( +
+ + +
+ ); +}; + +export default SelectProvider; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/components/createProviderCardItems.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/createProviderCardItems.tsx new file mode 100644 index 000000000..5e479796e --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/createProviderCardItems.tsx @@ -0,0 +1,46 @@ +import React from 'react'; +import { SelectableGalleryItem } from 'src/modules/Providers/utils/components/Galerry/SelectableGallery'; + +import { V1beta1Provider } from '@kubev2v/types'; + +import providerTypes from '../constanats/providerTypes'; + +import { ProviderCardContent } from './ProviderCardContent'; +import { ProviderCardTitle } from './providerCardTitle'; + +/** + * Generates an object containing the items for the provider card gallery. + * Each item includes the title, logo, and content components for a provider. + * @param {V1beta1Provider[]} providers - The array of providers to generate gallery items for. + * @returns {Record} An object mapping provider UIDs to card item data. + */ +export const createProviderCardItems = ( + providers: V1beta1Provider[], +): Record => { + const providerCardItems = {}; + + (providers || []).map((provider) => { + const typeObj = providerTypes[provider.spec.type]; + + providerCardItems[provider.metadata.uid] = { + title: , + logo: typeObj.logo, + content: , + }; + }); + + return providerCardItems; +}; + +/** + * Finds a provider by its unique identifier (UID) among a list of providers. + * @param {string} id - The unique identifier of the provider to find. + * @param {V1beta1Provider[]} providers - The array of providers to search through. + * @returns {V1beta1Provider | undefined} The provider found, or undefined if not found. + */ +export const findProviderByID = ( + id: string, + providers: V1beta1Provider[], +): V1beta1Provider | undefined => { + return providers.find((provider) => provider.metadata.uid === id); +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/components/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/index.ts new file mode 100644 index 000000000..399389d63 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/index.ts @@ -0,0 +1,12 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './ChipsToolbarProviders'; +export * from './createProviderCardItems'; +export * from './FiltersToolbarProviders'; +export * from './PlanCreateForm'; +export * from './ProviderCardContent'; +export * from './ProviderCardItems'; +export * from './providerCardTitle'; +export * from './ProvidersVirtualMachinesList'; +export * from './SearchInputProvider'; +export * from './SelectProvider'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/components/providerCardTitle.tsx b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/providerCardTitle.tsx new file mode 100644 index 000000000..b8dd426be --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/components/providerCardTitle.tsx @@ -0,0 +1,23 @@ +import React from 'react'; + +import { V1beta1Provider } from '@kubev2v/types'; +import { ResourceStatus } from '@openshift-console/dynamic-plugin-sdk'; +import Status from '@openshift-console/dynamic-plugin-sdk/lib/app/components/status/Status'; +import { Flex, FlexItem } from '@patternfly/react-core'; + +export const ProviderCardTitle: React.FC = ({ provider }) => { + return ( + + {provider.metadata.name} + + + + + + + ); +}; + +export type ProviderCardTitleProps = { + provider: V1beta1Provider; +}; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/constanats/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/create/constanats/index.ts new file mode 100644 index 000000000..ba720adfe --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/constanats/index.ts @@ -0,0 +1,3 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './providerTypes'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/constanats/providerTypes.ts b/packages/forklift-console-plugin/src/modules/Plans/views/create/constanats/providerTypes.ts new file mode 100644 index 000000000..131208b3a --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/constanats/providerTypes.ts @@ -0,0 +1,32 @@ +import { + openshiftLogo, + openstackLogo, + ovaLogo, + redhatLogo, + vmLogo, +} from 'src/components/images/logos'; + +const providerTypes = { + vsphere: { + title: 'vSphere', + logo: vmLogo, + }, + ovirt: { + title: 'Red Hat Virtualization', + logo: redhatLogo, + }, + openstack: { + title: 'OpenStack', + logo: openstackLogo, + }, + ova: { + title: 'Open Virtual Appliance (OVA)', + logo: ovaLogo, + }, + openshift: { + title: 'OpenShift Virtualization', + logo: openshiftLogo, + }, +}; + +export default providerTypes; diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/create/index.ts new file mode 100644 index 000000000..8c03a5c40 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/index.ts @@ -0,0 +1,4 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './components'; +export * from './PlanCreatePage'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/states/PlanCreatePageStore.ts b/packages/forklift-console-plugin/src/modules/Plans/views/create/states/PlanCreatePageStore.ts new file mode 100644 index 000000000..8c9082a48 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/states/PlanCreatePageStore.ts @@ -0,0 +1,65 @@ +import { VmData } from 'src/modules/Providers/views'; + +export interface PlanCreatePageState { + nameFilter: string; + typeFilters: string[]; + selectedProviderUID: string; + selectedVMs: VmData[]; +} + +export const planCreatePageInitialState: PlanCreatePageState = { + nameFilter: '', + typeFilters: [], + selectedProviderUID: '', + selectedVMs: [], +}; + +export const SET_NAME_FILTER = 'SET_NAME_FILTER'; +export const UPDATE_TYPE_FILTERS = 'UPDATE_TYPE_FILTERS'; +export const SELECT_PROVIDER = 'SELECT_PROVIDER'; +export const UPDATE_SELECTED_VMS = 'UPDATE_SELECTED_VMS'; + +// Refine the action type to include specific payloads +interface SetNameFilterAction { + type: typeof SET_NAME_FILTER; + payload: string; +} + +interface UpdateTypeFiltersAction { + type: typeof UPDATE_TYPE_FILTERS; + payload: string[]; +} + +interface SelectProviderAction { + type: typeof SELECT_PROVIDER; + payload: string; +} + +interface UpdateSelectedVMsAction { + type: typeof UPDATE_SELECTED_VMS; + payload: VmData[]; +} + +type PlanCreatePageActionTypes = + | SetNameFilterAction + | UpdateTypeFiltersAction + | SelectProviderAction + | UpdateSelectedVMsAction; + +export function planCreatePageReducer( + state: typeof planCreatePageInitialState, + action: PlanCreatePageActionTypes, +): typeof planCreatePageInitialState { + switch (action.type) { + case SET_NAME_FILTER: + return { ...state, nameFilter: action.payload }; + case UPDATE_TYPE_FILTERS: + return { ...state, typeFilters: action.payload }; + case SELECT_PROVIDER: + return { ...state, selectedProviderUID: action.payload, selectedVMs: [] }; + case UPDATE_SELECTED_VMS: + return { ...state, selectedVMs: action.payload }; + default: + return state; + } +} diff --git a/packages/forklift-console-plugin/src/modules/Plans/views/create/states/index.ts b/packages/forklift-console-plugin/src/modules/Plans/views/create/states/index.ts new file mode 100644 index 000000000..4ee54a7eb --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Plans/views/create/states/index.ts @@ -0,0 +1,3 @@ +// @index(['./*', /style/g], f => `export * from '${f.path}';`) +export * from './PlanCreatePageStore'; +// @endindex diff --git a/packages/forklift-console-plugin/src/modules/Providers/utils/components/Galerry/SelectableCard.tsx b/packages/forklift-console-plugin/src/modules/Providers/utils/components/Galerry/SelectableCard.tsx index e57433e5a..88f8b75d9 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/utils/components/Galerry/SelectableCard.tsx +++ b/packages/forklift-console-plugin/src/modules/Providers/utils/components/Galerry/SelectableCard.tsx @@ -1,6 +1,6 @@ import React, { ReactNode } from 'react'; -import { Card, CardBody, CardTitle, Level, LevelItem } from '@patternfly/react-core'; +import { Card, CardBody, CardTitle, Split, SplitItem } from '@patternfly/react-core'; interface SelectableCardProps { /** The title of the card. It can be any element - a string, a React component, etc. */ @@ -51,10 +51,10 @@ export const SelectableCard: React.FC = ({ > {titleLogo ? ( - - {titleLogo} - {title} - + + {titleLogo} + {title} + ) : ( {title} diff --git a/packages/forklift-console-plugin/src/modules/Providers/utils/components/Galerry/SelectableGallery.tsx b/packages/forklift-console-plugin/src/modules/Providers/utils/components/Galerry/SelectableGallery.tsx index f56aa62bf..38a980b42 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/utils/components/Galerry/SelectableGallery.tsx +++ b/packages/forklift-console-plugin/src/modules/Providers/utils/components/Galerry/SelectableGallery.tsx @@ -8,7 +8,7 @@ import './SelectableGallery.style.css'; export interface SelectableGalleryItem { /** The title of the item */ - title: string; + title: ReactNode; /** The logo of the item */ logo?: ReactNode; /** The content of the item */ diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/create/components/providerCardItems.ts b/packages/forklift-console-plugin/src/modules/Providers/views/create/components/providerCardItems.ts new file mode 100644 index 000000000..2a065b6a9 --- /dev/null +++ b/packages/forklift-console-plugin/src/modules/Providers/views/create/components/providerCardItems.ts @@ -0,0 +1,36 @@ +import { + openshiftLogo, + openstackLogo, + ovaLogo, + redhatLogo, + vmLogo, +} from 'src/components/images/logos'; +import { SelectableGalleryItem } from 'src/modules/Providers/utils/components/Galerry/SelectableGallery'; + +export const providerCardItems: Record = { + vsphere: { + title: 'vSphere', + logo: vmLogo, + content: "vSphere is VMware's cloud computing virtualization platform.", + }, + ovirt: { + title: 'Red Hat Virtualization', + logo: redhatLogo, + content: 'Red Hat Virtualization (RHV) is a virtualization platform from Red Hat.', + }, + openstack: { + title: 'OpenStack', + logo: openstackLogo, + content: 'OpenStack is a cloud computing platform that controls large pools of resources.', + }, + ova: { + title: 'Open Virtual Appliance (OVA)', + logo: ovaLogo, + content: 'OVA file is a virtual appliance used by virtualization applications.', + }, + openshift: { + title: 'OpenShift Virtualization', + logo: openshiftLogo, + content: 'OpenShift Virtualization run and manage virtual machine in OpenShift.', + }, +}; diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/create/components/providerCardItems.tsx b/packages/forklift-console-plugin/src/modules/Providers/views/create/components/providerCardItems.tsx deleted file mode 100644 index 5e6cb6678..000000000 --- a/packages/forklift-console-plugin/src/modules/Providers/views/create/components/providerCardItems.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import React from 'react'; -import { SelectableGalleryItem } from 'src/modules/Providers/utils/components/Galerry/SelectableGallery'; - -import openshiftImg from '../images/openshift.svg'; -import openstackImg from '../images/openstack.svg'; -import ovaImg from '../images/ova.svg'; -import redhatImg from '../images/redhat.svg'; -import vmImg from '../images/vm.svg'; - -const openshiftLogo = ( - PatternFly logo -); - -const openstackLogo = ( - PatternFly logo -); - -const vmLogo = ( - PatternFly logo -); - -const redhatLogo = ( - PatternFly logo -); - -const ovaLogo = ( - PatternFly logo -); - -export const providerCardItems: Record = { - vsphere: { - title: 'vSphere', - logo: vmLogo, - content: "vSphere is VMware's cloud computing virtualization platform.", - }, - ovirt: { - title: 'Red Hat Virtualization', - logo: redhatLogo, - content: 'Red Hat Virtualization (RHV) is a virtualization platform from Red Hat.', - }, - openstack: { - title: 'OpenStack', - logo: openstackLogo, - content: 'OpenStack is a cloud computing platform that controls large pools of resources.', - }, - ova: { - title: 'Open Virtual Appliance (OVA)', - logo: ovaLogo, - content: 'OVA file is a virtual appliance used by virtualization applications.', - }, - openshift: { - title: 'OpenShift Virtualization', - logo: openshiftLogo, - content: 'OpenShift Virtualization run and manage virtual machine in OpenShift.', - }, -}; diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/create/images/openstack.svg b/packages/forklift-console-plugin/src/modules/Providers/views/create/images/openstack.svg deleted file mode 100644 index bcd9934c1..000000000 --- a/packages/forklift-console-plugin/src/modules/Providers/views/create/images/openstack.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/details/components/CredentialsSection/components/BaseCredentialsSection.style.css b/packages/forklift-console-plugin/src/modules/Providers/views/details/components/CredentialsSection/components/BaseCredentialsSection.style.css index 36f63c97d..016eee94d 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/details/components/CredentialsSection/components/BaseCredentialsSection.style.css +++ b/packages/forklift-console-plugin/src/modules/Providers/views/details/components/CredentialsSection/components/BaseCredentialsSection.style.css @@ -29,6 +29,7 @@ .forklift-section-secret-edit{ padding-top: var(--pf-global--spacer--md); + padding-bottom: var(--pf-global--spacer--sm); } .forklift-section-secret-edit-switch { diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/ProviderVirtualMachines.tsx b/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/ProviderVirtualMachines.tsx index cb312258e..850afa54a 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/ProviderVirtualMachines.tsx +++ b/packages/forklift-console-plugin/src/modules/Providers/views/details/tabs/VirtualMachines/ProviderVirtualMachines.tsx @@ -49,7 +49,7 @@ export const ProviderVirtualMachines: React.FC<{ name: string; namespace: string To migrate virtual machines from {name} provider, select the virtual machines to migrate from the list of available virtual machines and click the{' '} - Migrate button. + Create migration plan button. diff --git a/packages/forklift-console-plugin/src/modules/Providers/views/migrate/ProvidersCreateVmMigrationPage.tsx b/packages/forklift-console-plugin/src/modules/Providers/views/migrate/ProvidersCreateVmMigrationPage.tsx index 5b60076ec..4e08e0ef6 100644 --- a/packages/forklift-console-plugin/src/modules/Providers/views/migrate/ProvidersCreateVmMigrationPage.tsx +++ b/packages/forklift-console-plugin/src/modules/Providers/views/migrate/ProvidersCreateVmMigrationPage.tsx @@ -27,7 +27,7 @@ const ProvidersCreateVmMigrationPage: FC = () => { return ( - + {state.flow.apiError && (