Skip to content

Commit

Permalink
standardpage inside drawer
Browse files Browse the repository at this point in the history
Signed-off-by: Radoslaw Szwajkowski <[email protected]>
  • Loading branch information
rszwajko committed Jan 18, 2024
1 parent db73a94 commit 5a534b1
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 69 deletions.
2 changes: 1 addition & 1 deletion packages/common/src/components/TableView/TableView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export function TableView<T>({
currentNamespace,
Header,
}: TableViewProps<T>) {
const hasChildren = children.filter(Boolean).length > 0;
const hasChildren = children?.filter(Boolean)?.length > 0;
const columnSignature = visibleColumns.map(({ resourceFieldId: id }) => id).join();
return (
<TableComposable aria-label={ariaLabel} variant="compact" isStickyHeader>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { OpenShiftVirtualMachinesCells } from './OpenShiftVirtualMachinesRow';
import { ProviderVirtualMachinesProps } from './ProviderVirtualMachines';
import { getOpenShiftFeatureMap, getVmPowerState } from './utils';

const openShiftVmFieldsMetadataFactory: ResourceFieldFactory = (t) => [
export const openShiftVmFieldsMetadataFactory: ResourceFieldFactory = (t) => [
{
resourceFieldId: 'name',
jsonPath: '$.name',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ export const ProviderVirtualMachinesList: FC<ProviderVirtualMachinesListProps> =
);
};

const concernsMatcher: ValueMatcher = {
export const concernsMatcher: ValueMatcher = {
filterType: 'concerns',
matchValue: (concerns: Concern[]) => (filter: string) =>
Array.isArray(concerns) &&
concerns.some(({ category, label }) => category === filter || label === filter),
};

const featuresMatcher: ValueMatcher = {
export const featuresMatcher: ValueMatcher = {
filterType: 'features',
matchValue: (features: { [key: string]: boolean }) => (filter: string) => !!features?.[filter],
};
Original file line number Diff line number Diff line change
@@ -1,70 +1,128 @@
import React, { useState } from 'react';
import StandardPage from 'src/components/page/StandardPage';
import { useForkliftTranslation } from 'src/utils/i18n';

import { EnumFilter, SearchableGroupedEnumFilter } from '@kubev2v/common';
import { ProviderModelGroupVersionKind } from '@kubev2v/types';
import { ResourceLink } from '@openshift-console/dynamic-plugin-sdk';
import { DescriptionList, Form, FormGroup, TextInput } from '@patternfly/react-core';
import {
Button,
DescriptionList,
DescriptionListDescription,
DescriptionListGroup,
DescriptionListTerm,
Drawer,
DrawerActions,
DrawerCloseButton,
DrawerContent,
DrawerContentBody,
DrawerHead,
DrawerPanelContent,
Form,
FormGroup,
TextInput,
} from '@patternfly/react-core';

import { DetailsItem } from '../../utils';
import { concernsMatcher, featuresMatcher, VmData } from '../details';

import { PageAction, setPlanName } from './actions';
import { CreateVmMigrationPageState } from './reducer';

export const PlansCreateForm = ({
state: { newPlan: plan, validation },
state: {
newPlan: plan,
validation,
selectedVms,
vmFieldsFactory: [vmFieldsFactory, RowMapper],
},
dispatch,
}: {
state: CreateVmMigrationPageState;
dispatch: (action: PageAction<unknown, unknown>) => void;
}) => {
const { t } = useForkliftTranslation();
const vmFields = vmFieldsFactory(t);
const [isNameEdited, setIsNameEdited] = useState(false);
const [isVmDetails, setIsVmDetails] = useState(false);
return (
<DescriptionList
className="forklift-create-provider-edit-section"
columnModifier={{
default: '1Col',
}}
>
{isNameEdited ? (
<Form>
<FormGroup
label={t('Plan name')}
isRequired
fieldId="planName"
validated={validation.name}
>
<TextInput
isRequired
type="text"
id="planName"
value={plan.metadata.name}
validated={validation.name}
onChange={(value) => dispatch(setPlanName(value?.trim() ?? '', []))}
<Drawer isExpanded={isVmDetails}>
<DrawerContent
panelContent={
<DrawerPanelContent widths={{ default: 'width_75' }}>
<DrawerHead>
<DrawerActions>
<DrawerCloseButton onClick={() => setIsVmDetails(false)} />
</DrawerActions>
</DrawerHead>
<StandardPage<VmData>
title={t('Selected VMs')}
dataSource={[selectedVms, true, false]}
fieldsMetadata={vmFields}
RowMapper={RowMapper}
namespace={plan.spec.provider?.source?.namespace}
extraSupportedFilters={{
concerns: SearchableGroupedEnumFilter,
features: EnumFilter,
}}
extraSupportedMatchers={[concernsMatcher, featuresMatcher]}
/>
</FormGroup>
</Form>
) : (
<DetailsItem
title={t('Plan name')}
content={plan.metadata.name}
onEdit={() => setIsNameEdited(true)}
/>
)}
<DetailsItem
title={t('Source provider')}
content={
<ResourceLink
name={plan?.spec?.provider?.source?.name}
namespace={plan?.spec?.provider?.source?.namespace}
groupVersionKind={ProviderModelGroupVersionKind}
/>
</DrawerPanelContent>
}
/>
<DetailsItem
title={t('{{vmCount}} VMs selected ', { vmCount: plan.spec.vms.length })}
content={''}
/>
</DescriptionList>
>
<DrawerContentBody>
<DescriptionList
className="forklift-create-provider-edit-section"
columnModifier={{
default: '1Col',
}}
>
{isNameEdited ? (
<Form>
<FormGroup
label={t('Plan name')}
isRequired
fieldId="planName"
validated={validation.name}
>
<TextInput
isRequired
type="text"
id="planName"
value={plan.metadata.name}
validated={validation.name}
onChange={(value) => dispatch(setPlanName(value?.trim() ?? ''))}
/>
</FormGroup>
</Form>
) : (
<DetailsItem
title={t('Plan name')}
content={plan.metadata.name}
onEdit={() => setIsNameEdited(true)}
/>
)}
<DetailsItem
title={t('Source provider')}
content={
<ResourceLink
name={plan.spec.provider?.source?.name}
namespace={plan.spec.provider?.source?.namespace}
groupVersionKind={ProviderModelGroupVersionKind}
/>
}
/>
<DescriptionListGroup>
<DescriptionListTerm>{t('Selected VMs')}</DescriptionListTerm>
<DescriptionListDescription>
<Button onClick={() => setIsVmDetails(true)} variant="link" isInline>
{t('{{vmCount}} VMs selected ', { vmCount: plan.spec.vms?.length ?? 0 })}
</Button>
</DescriptionListDescription>
</DescriptionListGroup>
</DescriptionList>
</DrawerContentBody>
</DrawerContent>
</Drawer>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export interface PageAction<S, T> {

export interface PlanName {
name: string;
existingPlanNames: string[];
}

export interface PlanDescription {
Expand Down Expand Up @@ -71,14 +70,10 @@ export const setPlanDescription = (
payload: { description },
});

export const setPlanName = (
name: string,
existingPlanNames: string[],
): PageAction<CreateVmMigration, PlanName> => ({
export const setPlanName = (name: string): PageAction<CreateVmMigration, PlanName> => ({
type: 'SET_NAME',
payload: {
name,
existingPlanNames,
},
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
import { FC } from 'react';
import { Draft } from 'immer';
import { isProviderLocalOpenshift } from 'src/utils/resources';
import { v4 as randomId } from 'uuid';

import { V1beta1Plan, V1beta1Provider } from '@kubev2v/types';
import { DefaultRow, ResourceFieldFactory, RowProps, withTr } from '@kubev2v/common';
import { ProviderType, V1beta1Plan, V1beta1Provider } from '@kubev2v/types';

import { validateK8sName, Validation } from '../../utils';
import { planTemplate } from '../create/templates';
import { toId, VmData } from '../details';
import { openShiftVmFieldsMetadataFactory } from '../details/tabs/VirtualMachines/OpenShiftVirtualMachinesList';
import { openStackVmFieldsMetadataFactory } from '../details/tabs/VirtualMachines/OpenStackVirtualMachinesList';
import { ovaVmFieldsMetadataFactory } from '../details/tabs/VirtualMachines/OvaVirtualMachinesList';
import { oVirtVmFieldsMetadataFactory } from '../details/tabs/VirtualMachines/OVirtVirtualMachinesList';
import { OVirtVirtualMachinesCells } from '../details/tabs/VirtualMachines/OVirtVirtualMachinesRow';
import { vSphereVmFieldsMetadataFactory } from '../details/tabs/VirtualMachines/VSphereVirtualMachinesList';

import {
CreateVmMigration,
PageAction,
PlanAvailableProviders,
PlanDescription,
PlanExistingPlans,
PlanName,
PlanTargetNamespace,
PlanTargetProvider,
SET_AVAILABLE_PROVIDERS,
SET_DESCRIPTION,
SET_EXISTING_PLANS,
SET_NAME,
SET_TARGET_NAMESPACE,
SET_TARGET_PROVIDER,
SET_EXISTING_PLANS,
PlanExistingPlans,
} from './actions';

export interface CreateVmMigrationPageState {
Expand All @@ -36,6 +44,7 @@ export interface CreateVmMigrationPageState {
availableProviders: V1beta1Provider[];
selectedVms: VmData[];
existingPlans: V1beta1Plan[];
vmFieldsFactory: [ResourceFieldFactory, FC<RowProps<VmData>>];
}

const validateUniqueName = (name: string, existingPlanNames: string[]) =>
Expand All @@ -47,13 +56,16 @@ const actions: {
action: PageAction<CreateVmMigration, unknown>,
) => CreateVmMigrationPageState;
} = {
[SET_NAME](
draft,
{ payload: { name } }: PageAction<CreateVmMigration, PlanName>,
) {
[SET_NAME](draft, { payload: { name } }: PageAction<CreateVmMigration, PlanName>) {
draft.newPlan.metadata.name = name;
draft.validation.name =
validateK8sName(name) && validateUniqueName(name, draft.existingPlans.map(plan => plan?.metadata?.name ?? '')) ? 'success' : 'error';
validateK8sName(name) &&
validateUniqueName(
name,
draft.existingPlans.map((plan) => plan?.metadata?.name ?? ''),
)
? 'success'
: 'error';
return draft;
},
[SET_DESCRIPTION](
Expand Down Expand Up @@ -84,20 +96,27 @@ const actions: {
draft,
{ payload: { availableProviders } }: PageAction<CreateVmMigration, PlanAvailableProviders>,
) {
if (!availableProviders?.length) {
draft.availableProviders = [];
return draft;
}

draft.availableProviders = availableProviders;
const targetProvider = draft.newPlan.spec.provider.destination;
// set the default provider if none is set
// reset the provider if provider was removed
if (
!targetProvider ||
!availableProviders.find((p) => p?.metadata?.name === targetProvider.name)
) {
// set the default provider if none is set
// reset the provider if provider was removed
const firstHostProvider = availableProviders.find((p) => isProviderLocalOpenshift(p));
draft.newPlan.spec.provider.destination =
firstHostProvider && getObjectRef(firstHostProvider);
// there might be no host (or other openshift) provider in the namespace
draft.newPlan.spec.provider.destination = firstHostProvider
? getObjectRef(firstHostProvider)
: undefined;
draft.newPlan.spec.targetNamespace = undefined;
draft.validation.targetNamespace = 'default';
}
draft.availableProviders = availableProviders;
return draft;
},
[SET_EXISTING_PLANS](
Expand Down Expand Up @@ -168,4 +187,24 @@ export const createInitialState = ({
name: 'default',
targetNamespace: 'default',
},
vmFieldsFactory: resourceFieldsForType(sourceProvider?.spec?.type as ProviderType),
});

export const resourceFieldsForType = (
type: ProviderType,
): [ResourceFieldFactory, FC<RowProps<VmData>>] => {
switch (type) {
case 'openshift':
return [openShiftVmFieldsMetadataFactory, DefaultRow];
case 'openstack':
return [openStackVmFieldsMetadataFactory, DefaultRow];
case 'ova':
return [ovaVmFieldsMetadataFactory, DefaultRow];
case 'ovirt':
return [oVirtVmFieldsMetadataFactory, withTr(OVirtVirtualMachinesCells)];
case 'vsphere':
return [vSphereVmFieldsMetadataFactory, DefaultRow];
default:
return [() => [], DefaultRow];
}
};

0 comments on commit 5a534b1

Please sign in to comment.