Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MTV-1726: Edit VMs list in migration plan #1414

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
"Edit StorageMap": "Edit StorageMap",
"Edit URL": "Edit URL",
"Edit VDDK init image": "Edit VDDK init image",
"Edit virtual machines": "Edit virtual machines",
"Empty": "Empty",
"Endpoint": "Endpoint",
"Endpoint type": "Endpoint type",
Expand Down Expand Up @@ -485,6 +486,8 @@
"The chosen provider is no longer available.": "The chosen provider is no longer available.",
"The current certificate does not match the certificate fetched from URL. Manually validate the fingerprint before proceeding.": "The current certificate does not match the certificate fetched from URL. Manually validate the fingerprint before proceeding.",
"The edit mappings button is disabled if the plan started running and at least one virtual machine was migrated successfully or when the plan status does not enable editing.": "The edit mappings button is disabled if the plan started running and at least one virtual machine was migrated successfully or when the plan status does not enable editing.",
"The edit virtual machines button is disabled if the plan started running and at least one virtual machine was migrated successfully.": "The edit virtual machines button is disabled if the plan started running and at least one virtual machine was migrated successfully.",
"The edit virtual machines button is disabled while the plan is not editable.": "The edit virtual machines button is disabled while the plan is not editable.",
"The interval in minutes for precopy. Default value is 60.": "The interval in minutes for precopy. Default value is 60.",
"The interval in seconds for snapshot pooling. Default value is 10.": "The interval in seconds for snapshot pooling. Default value is 10.",
"The limit for CPU usage by the controller, specified in milliCPU. Default value is 500m.": "The limit for CPU usage by the controller, specified in milliCPU. Default value is 500m.",
Expand Down Expand Up @@ -524,7 +527,9 @@
"Update credentials": "Update credentials",
"Update hooks": "Update hooks",
"Update mappings": "Update mappings",
"Update migration plan": "Update migration plan",
"Update providers": "Update providers",
"Update virtual machines": "Update virtual machines",
"Updated": "Updated",
"Upload": "Upload",
"URL": "URL",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import React, { useState } from 'react';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is basically a copy of packages/forklift-console-plugin/src/components/page/StandardPageWithSelection.tsx but without selection, only expansion


import { RowProps, withTr } from '@kubev2v/common';
import { Td, Th } from '@patternfly/react-table';

import StandardPage, { StandardPageProps } from './StandardPage';

export function withRowExpansion<T>({ CellMapper, isExpanded, toggleExpandFor }) {
const Enhanced = (props: RowProps<T>) => (
<>
{isExpanded && (
<Td
expand={{
rowIndex: props.resourceIndex,
isExpanded: isExpanded(props.resourceData),
onToggle: () => toggleExpandFor([props.resourceData]),
}}
/>
)}
<CellMapper {...props} />
</>
);
Enhanced.displayName = `${CellMapper.displayName || 'CellMapper'}WithExpansion`;
return Enhanced;
}

export interface IdBasedExpansionProps<T> {
/**
* @returns string that can be used as an unique identifier
*/
toId?: (item: T) => string;

/**
* onExpand is called when expand changes
*/
onExpand?: (expandedIds: string[]) => void;

/**
* Expanded ids
*/
expandedIds?: string[];
}

/**
* Adds ID based expansion to StandardPage component.
* Contract:
* 1. IDs provided with toId() function are unique and constant in time
*/
export function withIdBasedExpansion<T>({
toId,
onExpand,
expandedIds: initialExpandedIds,
}: IdBasedExpansionProps<T>) {
const Enhanced = (props: StandardPageProps<T>) => {
const [expandedIds, setExpandedIds] = useState(initialExpandedIds);

const isExpanded =
onExpand || expandedIds ? (item: T) => expandedIds.includes(toId(item)) : undefined;

const toggleExpandFor = (items: T[]) => {
const ids = items.map(toId);
const allExpanded = ids.every((id) => expandedIds?.includes(id));
const newExpandedIds = [
...(expandedIds || []).filter((it) => !ids.includes(it)),
...(allExpanded ? [] : ids),
];

setExpandedIds(newExpandedIds);
if (onExpand) {
onExpand(newExpandedIds);
}
};

const { CellMapper, ExpandedComponent, ...rest } = props;

const RowMapper = withTr(
withRowExpansion({
CellMapper: CellMapper,
isExpanded,
toggleExpandFor,
}),
ExpandedComponent,
);

return (
<StandardPage
{...rest}
expandedIds={expandedIds}
toId={toId}
RowMapper={RowMapper}
HeaderMapper={() => <Th />}
GlobalActionToolbarItems={props.GlobalActionToolbarItems}
/>
);
};
Enhanced.displayName = 'StandardPageWithExpansion';
return Enhanced;
}

/**
* Properties for the `StandardPageWithExpansion` component.
* These properties extend the base `StandardPageProps` and add additional ones related to expansion.
*
* @typedef {Object} StandardPageWithExpansionProps
* @property {Function} toId - A function that returns a unique identifier for each item.
* @property {Function} onExpand - A callback function that is triggered when row is expanded or un expanded.
* @property {string[]} expandedIds - An array of identifiers for the currently expanded items.
* @property {...StandardPageProps<T>} - Other props that are passed through to the `StandardPage` component.
*
* @template T - The type of the items being displayed in the table.
*/
export interface StandardPageWithExpansionProps<T> extends StandardPageProps<T> {
toId?: (item: T) => string;
onExpand?: (expandedIds: string[]) => void;
expandedIds?: string[];
}

/**
* Renders a standard page with expansion capabilities.
* This component wraps the `StandardPage` component and adds support for row expansion.
* It uses the provided `toId`, `onExpand`, and `expandedIds` props to manage the expansion state.
*
* @param {Object} props - The properties passed to the component.
* @param {Function} props.toId - A function that returns a unique identifier for each item.
* @param {...StandardPageProps<T>} props - Other props that are passed through to the `StandardPage` component.
*
* @template T - The type of the items being displayed in the table.
*
* @example
* <StandardPageWithExpansion
* toId={item => item.id}
* // ...other props
* />
*/
export function StandardPageWithExpansion<T>(props: StandardPageWithExpansionProps<T>) {
const { toId, onExpand, expandedIds, ...rest } = props;

if (onExpand && (!toId || !expandedIds)) {
throw new Error('Missing required properties: toId, expandedIds');
}

const EnhancedStandardPage = withIdBasedExpansion<T>({
toId,
onExpand,
expandedIds,
});

return <EnhancedStandardPage {...rest} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type PlanEditAction = 'PLAN' | 'VMS';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will allow us next (with small changes like this) to edit plans too

Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const SelectSourceProvider: React.FC<{
state: CreateVmMigrationPageState;
dispatch: React.Dispatch<PageAction<CreateVmMigration, unknown>>;
filterDispatch: React.Dispatch<PlanCreatePageActionTypes>;
hideProviderSection?: boolean;
}> = ({
filterState,
providers,
Expand All @@ -27,6 +28,7 @@ export const SelectSourceProvider: React.FC<{
projectName,
dispatch,
filterDispatch,
hideProviderSection,
}) => {
const { t } = useForkliftTranslation();

Expand All @@ -45,16 +47,20 @@ export const SelectSourceProvider: React.FC<{

return (
<>
<Title headingLevel="h2">{t('Select source provider')}</Title>
{!hideProviderSection && (
<>
<Title headingLevel="h2">{t('Select source provider')}</Title>

<PlanCreateForm
providers={filteredProviders}
filterState={filterState}
filterDispatch={filterDispatch}
dispatch={dispatch}
state={state}
projectName={projectName}
/>
<PlanCreateForm
providers={filteredProviders}
filterState={filterState}
filterDispatch={filterDispatch}
dispatch={dispatch}
state={state}
projectName={projectName}
/>
</>
)}

{filterState.selectedProviderUID && (
<>
Expand Down
Loading
Loading