Skip to content

Commit

Permalink
MTV-1726: Edit VMs list in migration plan
Browse files Browse the repository at this point in the history
Signed-off-by: Joachim Schuler <[email protected]>
  • Loading branch information
jschuler committed Dec 16, 2024
1 parent 96365a3 commit c94fceb
Show file tree
Hide file tree
Showing 25 changed files with 1,281 additions and 194 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,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 @@ -483,6 +484,7 @@
"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 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 @@ -521,7 +523,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';

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';
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export const SelectSourceProvider: React.FC<{
filterDispatch: React.Dispatch<PlanCreatePageActionTypes>;
providers: V1beta1Provider[];
selectedProvider: V1beta1Provider;
}> = ({ filterState, filterDispatch, providers, selectedProvider }) => {
hideProviderSection?: boolean;
}> = ({ filterState, filterDispatch, providers, selectedProvider, hideProviderSection }) => {
const { t } = useForkliftTranslation();

// Get the ready providers (note: currently forklift does not allow filter be status.phase)
Expand All @@ -33,13 +34,17 @@ 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}
/>
<PlanCreateForm
providers={filteredProviders}
filterState={filterState}
filterDispatch={filterDispatch}
/>
</>
)}

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

0 comments on commit c94fceb

Please sign in to comment.