Skip to content

Commit

Permalink
Providers details page
Browse files Browse the repository at this point in the history
Signed-off-by: yaacov <yzamir@redhat.com>
  • Loading branch information
yaacov committed Jul 10, 2023
1 parent 2c0201e commit 4a0cfc5
Show file tree
Hide file tree
Showing 185 changed files with 9,455 additions and 2 deletions.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/forklift-console-plugin/plugin-extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { NavSection } from '@openshift-console/dynamic-plugin-sdk';
import { extensions as mockConsoleExtensions } from './src/__mock-console-extension/dynamic-plugin';
import { extensions as networkMapExtensions } from './src/modules/NetworkMaps/dynamic-plugin';
import { extensions as planExtensions } from './src/modules/Plans/dynamic-plugin';
import { extensions as providerExtensions } from './src/modules/Providers/dynamic-plugin';
import { extensions as providerExtensions } from './src/modules/ProvidersNG/dynamic-plugin';
import { extensions as storageMapExtensions } from './src/modules/StorageMaps/dynamic-plugin';

const extensions: EncodedExtension[] = [
Expand Down
2 changes: 1 addition & 1 deletion packages/forklift-console-plugin/plugin-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { ConsolePluginMetadata } from '@openshift-console/dynamic-plugin-sd
import { exposedModules as mockExtensionModules } from './src/__mock-console-extension/dynamic-plugin';
import { exposedModules as networkMapModules } from './src/modules/NetworkMaps/dynamic-plugin';
import { exposedModules as planModules } from './src/modules/Plans/dynamic-plugin';
import { exposedModules as providerModules } from './src/modules/Providers/dynamic-plugin';
import { exposedModules as providerModules } from './src/modules/ProvidersNG/dynamic-plugin';
import { exposedModules as storageMapModules } from './src/modules/StorageMaps/dynamic-plugin';
import pkg from './package.json';

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.forklift-dropdown {
margin: 0;
padding: 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react';
import { useForkliftTranslation } from 'src/utils/i18n';

import { Dropdown, DropdownPosition, DropdownToggle, KebabToggle } from '@patternfly/react-core';

import { useToggle } from '../hooks';
import { ModalHOC } from '../modals';
import { CellProps } from '../views';

import { ProviderActionsDropdownItems } from './ProviderActionsDropdownItems';

import './ProviderActionsDropdown.style.css';

/**
* ProviderActionsKebabDropdown_ is a helper component that displays a kebab dropdown menu.
* @param {CellProps} props - The properties passed to this component.
* @param {ProviderWithInventory} props.data - The data to be used in ProviderActionsDropdownItems.
* @returns {React.Element} The rendered dropdown menu component.
*/
const ProviderActionsKebabDropdown_: React.FC<ProviderActionsDropdownProps> = ({
data,
isKebab,
}) => {
const { t } = useForkliftTranslation();

// Hook for managing the open/close state of the dropdown
const [isDropdownOpen, toggle] = useToggle();

// Returning the Dropdown component from PatternFly library
return (
<Dropdown
onSelect={toggle}
isOpen={isDropdownOpen}
isPlain
position={DropdownPosition.right}
className={isKebab ? undefined : 'forklift-dropdown pf-c-menu-toggle'}
toggle={
isKebab ? (
<KebabToggle id="toggle-kebab" onToggle={toggle} />
) : (
<DropdownToggle id="toggle-basic" onToggle={toggle}>
{t('Actions')}
</DropdownToggle>
)
}
dropdownItems={ProviderActionsDropdownItems({ data })}
/>
);
};

/**
* ProviderActionsDropdown is a component that provides a context for the dropdown menu.
* It uses a ModalProvider to manage modals that may be used in the dropdown menu.
* @param {CellProps} props - The properties passed to this component.
* @returns {React.Element} The rendered component with a ModalProvider context.
*/
export const ProviderActionsDropdown: React.FC<ProviderActionsDropdownProps> = (props) => (
<ModalHOC>
<ProviderActionsKebabDropdown_ {...props} />
</ModalHOC>
);

export interface ProviderActionsDropdownProps extends CellProps {
isKebab?: boolean;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { useForkliftTranslation } from 'src/utils/i18n';

import { ProviderModel, ProviderModelRef } from '@kubev2v/types';
import { DropdownItem } from '@patternfly/react-core';

import { DeleteModal, useModal } from '../modals';
import { getResourceUrl, ProviderData } from '../utils';

export const ProviderActionsDropdownItems = ({ data }: ProviderActionsDropdownItemsProps) => {
const { t } = useForkliftTranslation();
const { showModal } = useModal();

const { provider } = data;

const providerURL = getResourceUrl({
reference: ProviderModelRef,
name: provider?.metadata?.name,
namespace: provider?.metadata?.namespace,
});

return [
<DropdownItem
key="EditProvider"
component={<Link to={providerURL}>{t('Edit Provider')}</Link>}
/>,
<DropdownItem
key="delete"
isDisabled={!data?.permissions?.canDelete}
onClick={() => showModal(<DeleteModal resource={provider} model={ProviderModel} />)}
>
{t('Delete Provider')}
</DropdownItem>,
];
};

interface ProviderActionsDropdownItemsProps {
data: ProviderData;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// @index('./*.tsx', f => `export * from '${f.path}';`)
export * from './ProviderActionsDropdown';
export * from './ProviderActionsDropdownItems';
// @endindex
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { ProviderModel, ProviderModelGroupVersionKind } from '@kubev2v/types';
import { EncodedExtension } from '@openshift/dynamic-plugin-sdk';
import {
CreateResource,
ModelMetadata,
ResourceDetailsPage,
ResourceListPage,
ResourceNSNavItem,
} from '@openshift-console/dynamic-plugin-sdk';
import type { ConsolePluginMetadata } from '@openshift-console/dynamic-plugin-sdk-webpack/lib/schema/plugin-package';

export const exposedModules: ConsolePluginMetadata['exposedModules'] = {
ProvidersListPage: './modules/ProvidersNG/views/list/ProvidersListPage',
ProviderDetailsPage: './modules/ProvidersNG/views/details/ProviderDetailsPage',
ProvidersCreatePage: './modules/ProvidersNG/views/create/ProvidersCreatePage',
};

export const extensions: EncodedExtension[] = [
{
type: 'console.navigation/resource-ns',
properties: {
id: 'providers-ng',
insertAfter: 'importSeparator',
perspective: 'admin',
section: 'migration',
// t('plugin__forklift-console-plugin~Providers for virtualization')
name: '%plugin__forklift-console-plugin~Providers for virtualization%',
model: ProviderModelGroupVersionKind,
dataAttributes: {
'data-quickstart-id': 'qs-nav-providers',
'data-testid': 'providers-nav-item',
},
},
} as EncodedExtension<ResourceNSNavItem>,

{
type: 'console.page/resource/list',
properties: {
component: {
$codeRef: 'ProvidersListPage',
},
model: ProviderModelGroupVersionKind,
},
} as EncodedExtension<ResourceListPage>,

{
type: 'console.page/resource/details',
properties: {
component: {
$codeRef: 'ProviderDetailsPage',
},
model: ProviderModelGroupVersionKind,
},
} as EncodedExtension<ResourceDetailsPage>,

{
type: 'console.model-metadata',
properties: {
model: ProviderModelGroupVersionKind,
...ProviderModel,
},
} as EncodedExtension<ModelMetadata>,

{
type: 'console.resource/create',
properties: {
component: {
$codeRef: 'ProvidersCreatePage',
},
model: ProviderModelGroupVersionKind,
...ProviderModel,
},
} as EncodedExtension<CreateResource>,
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { V1beta1Provider } from '@kubev2v/types';

import { getIsManaged, getIsOnlySource, getIsTarget } from '../../utils';

describe('Provider Utils', () => {
describe('getIsManaged', () => {
it('should return true if the provider has owner references', () => {
const provider: V1beta1Provider = {
metadata: {
ownerReferences: [
{
apiVersion: '',
kind: '',
name: '',
uid: '',
},
],
},
apiVersion: '',
kind: '',
};

expect(getIsManaged(provider)).toBe(true);
});

it('should return false if the provider has no owner references', () => {
const provider: V1beta1Provider = {
metadata: {},
apiVersion: '',
kind: '',
};

expect(getIsManaged(provider)).toBe(false);
});
});

describe('getIsTarget', () => {
it('should return true if the provider type is included in TARGET_PROVIDER_TYPES', () => {
const provider: V1beta1Provider = {
metadata: {},
apiVersion: '',
kind: '',
spec: {
type: 'openshift',
},
};

expect(getIsTarget(provider)).toBe(true);
});

it('should return false if the provider type is not included in TARGET_PROVIDER_TYPES', () => {
const provider: V1beta1Provider = {
metadata: {},
apiVersion: '',
kind: '',
spec: {
type: 'nonTargetType',
},
};

expect(getIsTarget(provider)).toBe(false);
});
});

describe('getIsOnlySource', () => {
it('should return true if the provider type is included in SOURCE_ONLY_PROVIDER_TYPES', () => {
const provider: V1beta1Provider = {
metadata: {},
apiVersion: '',
kind: '',
spec: {
type: 'vsphere',
},
};

expect(getIsOnlySource(provider)).toBe(true);
});

it('should return false if the provider type is not included in SOURCE_ONLY_PROVIDER_TYPES', () => {
const provider: V1beta1Provider = {
metadata: {},
apiVersion: '',
kind: '',
spec: {
type: 'nonSourceType',
},
};

expect(getIsOnlySource(provider)).toBe(false);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// @index(['./*', /__/g], f => `export * from '${f.path}';`)
export * from './useGetDeleteAndEditAccessReview';
export * from './useK8sWatchProviderNames';
export * from './useK8sWatchSecretData';
export * from './useProviderInventory';
export * from './useProvidersInventoryList';
export * from './useToggle';
export * from './utils';
// @endindex
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { K8sModel, useAccessReview } from '@openshift-console/dynamic-plugin-sdk';

import { ProvidersPermissionStatus } from '../utils';

/**
* Type for the parameters of the useGetDeleteAndEditAccessReview custom hook.
*
* @typedef {Object} K8sModelAccessReviewParams
* @property {K8sModel} model - The Kubernetes model to check permissions on.
* @property {string} [name] - The name of the specific instance of the model, if any.
* @property {string} [namespace] - The namespace in which to review access permissions.
*/
interface K8sModelAccessReviewParams {
model: K8sModel;
name?: string;
namespace?: string;
}

/**
* A React hook that checks permissions for different actions on a Kubernetes model within a specified namespace.
* @param {K8sModelAccessReviewParams} param0 - An object that contains model, name and namespace details.
* @returns {Object} An object containing permissions and a loading state.
*/
export const useGetDeleteAndEditAccessReview: UseAccessReviewFn = ({ model, name, namespace }) => {
const [canCreate, loadingCreate] = useAccessReview({
group: model.apiGroup,
resource: model.plural,
verb: 'create',
namespace,
});

const [canPatch, loadingPatch] = useAccessReview({
group: model.apiGroup,
resource: model.plural,
verb: 'patch',
name,
namespace,
});

const [canDelete, loadingDelete] = useAccessReview({
group: model.apiGroup,
resource: model.plural,
verb: 'delete',
name,
namespace,
});

const [canGet, loadingGet] = useAccessReview({
group: model.apiGroup,
resource: model.plural,
verb: 'get',
name,
namespace,
});

return {
canCreate,
canPatch,
canDelete,
canGet,
loading: loadingCreate || loadingPatch || loadingDelete || loadingGet,
};
};

type UseAccessReviewFn = (props: K8sModelAccessReviewParams) => ProvidersPermissionStatus;

export default useGetDeleteAndEditAccessReview;
Loading

0 comments on commit 4a0cfc5

Please sign in to comment.