Skip to content
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
7 changes: 3 additions & 4 deletions locales/en/plugin__forklift-console-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
"{{count}} VM migration_one": "{{count}} VM migration",
"{{count}} VM migration_other": "{{count}} VM migration",
"{{errorMessage}}": "{{errorMessage}}",
"{{hookType}} migration hook": "{{hookType}} migration hook",
"{{label}}": "{{label}}",
"{{label}} field is missing from the secret data.": "{{label}} field is missing from the secret data.",
"{{mapType}} name is required.": "{{mapType}} name is required.",
Expand Down Expand Up @@ -134,7 +133,6 @@
"Affinity rules": "Affinity rules",
"Affinity rules allows you to specify hard-and soft-affinity for virtual machines. It is possible to write matching rules against workloads (virtual machines and Pods) and Nodes.": "Affinity rules allows you to specify hard-and soft-affinity for virtual machines. It is possible to write matching rules against workloads (virtual machines and Pods) and Nodes.",
"All": "All",
"All changes saved": "All changes saved",
"All networks detected on the selected VMs require a mapping.": "All networks detected on the selected VMs require a mapping.",
"All past migration runs for this plan. This includes both successful and failed attempts, but detailed logs and other data are not available after the migration pods are deleted. If you retry an incomplete migration, only the failed VMs will migrate again.": "All past migration runs for this plan. This includes both successful and failed attempts, but detailed logs and other data are not available after the migration pods are deleted. If you retry an incomplete migration, only the failed VMs will migrate again.",
"All storages detected on the selected VMs require a mapping.": "All storages detected on the selected VMs require a mapping.",
Expand Down Expand Up @@ -177,7 +175,6 @@
"Building image...": "Building image...",
"By default, vNICs change during migration and static IPs linked to interface names are lost. Enable to preserve static IP configurations.": "By default, vNICs change during migration and static IPs linked to interface names are lost. Enable to preserve static IP configurations.",
"CA certificate": "CA certificate",
"Can not update plan hooks when the plan is not editable.": "Can not update plan hooks when the plan is not editable.",
"Cancel": "Cancel",
"Cancel virtual machines": "Cancel virtual machines",
"Cancel virtual machines migration?": "Cancel virtual machines migration?",
Expand Down Expand Up @@ -313,7 +310,9 @@
"Duplicate migration plan": "Duplicate migration plan",
"Each row must have both source and target storage selected": "Each row must have both source and target storage selected",
"Edit": "Edit",
"Edit {{hookTypeLowercase}} migration hook": "Edit {{hookTypeLowercase}} migration hook",
"Edit affinity rule": "Edit affinity rule",
"Edit Ansible hook configuration for your migration plan.": "Edit Ansible hook configuration for your migration plan.",
"Edit credentials": "Edit credentials",
"Edit cutover": "Edit cutover",
"Edit default transfer network": "Edit default transfer network",
Expand All @@ -330,6 +329,7 @@
"Edit provider web UI link": "Edit provider web UI link",
"Edit PVC name template": "Edit PVC name template",
"Edit root device": "Edit root device",
"Edit Settings": "Edit Settings",
"Edit step": "Edit step",
"Edit storage map": "Edit storage map",
"Edit target name": "Edit target name",
Expand Down Expand Up @@ -1038,7 +1038,6 @@
"Unknown power state": "Unknown power state",
"Unsupported provider type": "Unsupported provider type",
"Update credentials": "Update credentials",
"Update hooks": "Update hooks",
"Update mappings": "Update mappings",
"Update providers": "Update providers",
"Updated": "Updated",
Expand Down
3 changes: 1 addition & 2 deletions src/components/ModalForm/ModalForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { type ReactNode, useCallback, useState } from 'react';

import type { K8sResourceCommon } from '@openshift-console/dynamic-plugin-sdk';
import type { ModalComponent } from '@openshift-console/dynamic-plugin-sdk/lib/app/modal-support/ModalProvider';
import {
Alert,
Expand All @@ -21,7 +20,7 @@ import { useForkliftTranslation } from '@utils/i18n';
type ModalFormProps = {
title: ReactNode;
children: ReactNode;
onConfirm: () => Promise<K8sResourceCommon | undefined>;
onConfirm: () => Promise<unknown>;
variant?: ModalVariant;
confirmLabel?: string;
cancelLabel?: string;
Expand Down
2 changes: 1 addition & 1 deletion src/components/headers/SectionHeading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { FC, ReactNode } from 'react';

import { Title, type TitleProps } from '@patternfly/react-core';

type SectionHeadingProps = {
export type SectionHeadingProps = {
text: ReactNode;
className?: string;
id?: string;
Expand Down
45 changes: 45 additions & 0 deletions src/components/headers/SectionHeadingWithEdit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { FC } from 'react';

import { Button, ButtonVariant, Flex } from '@patternfly/react-core';
import { PencilAltIcon } from '@patternfly/react-icons';
import { useForkliftTranslation } from '@utils/i18n';

import SectionHeading, { type SectionHeadingProps } from './SectionHeading';

type SectionHeadingWithEditProps = Omit<
{
title: string;
editable: boolean;
onClick: () => void;
} & SectionHeadingProps,
'text'
>;

const SectionHeadingWithEdit: FC<SectionHeadingWithEditProps> = ({
editable,
onClick,
title,
...rest
}) => {
const { t } = useForkliftTranslation();
return (
<SectionHeading
{...rest}
text={
<Flex direction={{ default: 'row' }} gap={{ default: 'gapSm' }}>
{title}
<Button
icon={<PencilAltIcon />}
variant={ButtonVariant.link}
onClick={onClick}
isDisabled={!editable}
>
{t('Edit')}
</Button>
</Flex>
}
/>
);
};

export default SectionHeadingWithEdit;
29 changes: 4 additions & 25 deletions src/modules/Providers/modals/EditModal/utils/defaultOnConfirm.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
getValueByJsonPath,
jsonPathToPatch,
openApiJsonPathToPatch,
} from 'src/modules/Providers/utils/helpers/getValueByJsonPath';

import type { OpenApiJsonPath } from '@components/common/utils/types';
Expand All @@ -25,39 +25,18 @@ export const defaultOnConfirm = async ({
jsonPath: OpenApiJsonPath;
model: K8sModel;
}) => {
const path = getValueByJsonPath(resource, jsonPath);
const op = path ? REPLACE : ADD;
const value = getValueByJsonPath(resource, jsonPath);
const op = value ? REPLACE : ADD;

return k8sPatch<K8sResourceCommon>({
data: [
{
op,
path: jsonPathToPatch(path),
path: openApiJsonPathToPatch(resource, jsonPath),
value: newValue,
},
],
model,
resource,
});
};

/**
* Wraps the defaultOnConfirm method to convert the newValue from string to int before patching.
*/
export const defaultOnConfirmWithIntValue = async ({
jsonPath,
model,
newValue,
resource,
}: {
resource: K8sResourceCommon;
newValue: unknown;
jsonPath: OpenApiJsonPath;
model: K8sModel;
}) => {
// Convert the newValue from string to int
const intValue = parseInt(String(newValue), 10);

// Call the original method with the converted value
return defaultOnConfirm({ jsonPath, model, newValue: intValue, resource });
};
15 changes: 13 additions & 2 deletions src/modules/Providers/utils/helpers/getValueByJsonPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,19 @@ export const getValueByJsonPath = (obj: unknown, pathOrFunction: OpenApiJsonPath
return pathParts.reduce((path: any, key: string) => path?.[key], obj) as string;
};

export const jsonPathToPatch = (path: string | string[]) => {
let pathParts = typeof path === 'string' ? path.split('.') : path;
/**
* Converts a JSON path in dot notation to a JSON Patch path.
*
* @param obj - The object (not used in this function but kept for consistency with getValueByJsonPath).
* @param pathOrFunction - The JSON path (dot notation) or a function that returns the desired path.
* @returns The JSON Patch path as a string.
*/
export const openApiJsonPathToPatch = (obj: unknown, pathOrFunction: OpenApiJsonPath) => {
if (typeof pathOrFunction === 'function') {
return pathOrFunction(obj);
}

let pathParts = typeof pathOrFunction === 'string' ? pathOrFunction.split('.') : pathOrFunction;

pathParts = pathParts.map((pathPart) => pathPart.replaceAll('/', '~1'));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useK8sWatchForkliftController } from 'src/overview/hooks/useK8sWatchFor

import { Bullseye } from '@patternfly/react-core';

import SettingsCard from './cards/SettingsCard';
import SettingsCard from './components/SettingsCard';

const ForkliftControllerSettingsTab: FC = () => {
const [forkliftController, controllerLoaded, controllerLoadError] =
Expand Down
136 changes: 0 additions & 136 deletions src/overview/tabs/Settings/cards/EditField.tsx

This file was deleted.

Loading