Skip to content

Commit

Permalink
Merge pull request #738 from yaacov/refactor-concers-cell-renderer
Browse files Browse the repository at this point in the history
Refactor the concern cell renderer
  • Loading branch information
yaacov authored Sep 20, 2023
2 parents 9b06e18 + c9f3d66 commit 5044244
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"CreationTimestamp is a timestamp representing the server time when this object was created.\n It is not guaranteed to be set in happens-before order across separate operations.\n Clients may not set this value. It is represented in RFC3339 form and is in UTC.": "CreationTimestamp is a timestamp representing the server time when this object was created.\n It is not guaranteed to be set in happens-before order across separate operations.\n Clients may not set this value. It is represented in RFC3339 form and is in UTC.",
"CreationTimestamp is a timestamp representing the server time when this object was created.\n It is not guaranteed to be set in happens-before order across separate operations.\n Clients may not set this value. It is represented in RFC3339 form and is in UTC.": "CreationTimestamp is a timestamp representing the server time when this object was created.\n It is not guaranteed to be set in happens-before order across separate operations.\n Clients may not set this value. It is represented in RFC3339 form and is in UTC.",
"Credentials": "Credentials",
"Critical concerns": "Critical concerns",
"Custom certification used to verify the OpenStack REST API server, when empty use system certificate.": "Custom certification used to verify the OpenStack REST API server, when empty use system certificate.",
"Custom certification used to verify the RH Virtualization REST API server, when empty use system certificate.": "Custom certification used to verify the RH Virtualization REST API server, when empty use system certificate.",
"Data centers": "Data centers",
Expand Down Expand Up @@ -128,6 +129,7 @@
"Hosts": "Hosts",
"If true, the provider's REST API TLS certificate won't be validated.": "If true, the provider's REST API TLS certificate won't be validated.",
"If true, the provider's TLS certificate won't be validated.": "If true, the provider's TLS certificate won't be validated.",
"Information concerns": "Information concerns",
"Invalid application credential ID.": "Invalid application credential ID.",
"Invalid application credential name.": "Invalid application credential name.",
"Invalid application credential secret.": "Invalid application credential secret.",
Expand Down Expand Up @@ -352,6 +354,7 @@
"To troubleshoot, view the provider status available in the provider details page\n and check the Forklift controller pod logs.": "To troubleshoot, view the provider status available in the provider details page\n and check the Forklift controller pod logs.",
"Token": "Token",
"Total": "Total",
"Total: {{length}}": "Total: {{length}}",
"True": "True",
"Type": "Type",
"Type of authentication to use when connecting to OpenStack REST API.": "Type of authentication to use when connecting to OpenStack REST API.",
Expand Down Expand Up @@ -384,6 +387,7 @@
"vSphere product name": "vSphere product name",
"vSphere REST API password credentials.": "vSphere REST API password credentials.",
"vSphere REST API user name.": "vSphere REST API user name.",
"Warning concerns": "Warning concerns",
"Warning: The provided URL does not end with \"ovirt-engine/api\". Ensure it includes the correct path, like: https://rhv.com/ovirt-engine/api.": "Warning: The provided URL does not end with \"ovirt-engine/api\". Ensure it includes the correct path, like: https://rhv.com/ovirt-engine/api.",
"Warning: The provided URL does not end with \"sdk\". Ensure it includes the correct path, like: https://vcenter.com/sdk.": "Warning: The provided URL does not end with \"sdk\". Ensure it includes the correct path, like: https://vcenter.com/sdk.",
"Welcome": "Welcome",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react';
import { TFunction } from 'react-i18next';
import { TableCell } from 'src/modules/Providers/utils';
import { useForkliftTranslation } from 'src/utils/i18n';

import { Concern } from '@kubev2v/types';
import {
Expand All @@ -11,11 +13,12 @@ import { Button, Flex, FlexItem, Label, Popover, Stack, StackItem } from '@patte

import { VMCellProps } from './VMCellProps';

type ConcernCategories = {
category: 'Critical' | 'Information' | 'Warning';
label: string;
};

/**
* Renders a table cell containing concerns grouped by category.
*
* @param {VMCellProps} props - The properties of the VMConcernsCellRenderer component.
* @returns {ReactElement} The rendered table cell.
*/
export const VMConcernsCellRenderer: React.FC<VMCellProps> = ({ data }) => {
const groupedConcerns = groupConcernsByCategory(data?.vm?.concerns);

Expand All @@ -32,59 +35,123 @@ export const VMConcernsCellRenderer: React.FC<VMCellProps> = ({ data }) => {
);
};

const groupConcernsByCategory = (concerns: Concern[]): Record<string, ConcernCategories[]> => {
return (
concerns?.reduce((acc, concern) => {
acc[concern.category] = (acc[concern.category] || []).concat(concern);
return acc;
}, {}) || {}
);
};

/**
* Renders a popover for a specific concern category.
*
* @param {Object} props - The properties of the ConcernPopover component.
* @param {string} props.category - The category of the concern.
* @param {Concern[]} props.concerns - The list of concerns for the category.
* @returns {ReactElement} The rendered popover.
*/
const ConcernPopover: React.FC<{
category: string;
concerns: ConcernCategories[];
concerns: Concern[];
}> = ({ category, concerns }) => {
const { t } = useForkliftTranslation();

if (concerns.length < 1) return <></>;

return (
<Popover
aria-label={`${category} popover`}
headerContent={<div>{category} Concerns</div>}
headerContent={<div>{getCategoryTitle(category, t)}</div>}
bodyContent={<ConcernList concerns={concerns} />}
footerContent={`Total: ${concerns.length}`}
footerContent={t('Total: {{length}}', { length: concerns.length })}
>
<Button variant="link" className="forklift-page-provider-vm_concern-button">
<ConcernLabel category={category} count={concerns.length} />
<Label color={getCategoryColor(category)} icon={getCategoryIcon(category)}>
{concerns.length}
</Label>
</Button>
</Popover>
);
};

const ConcernList: React.FC<{ concerns: ConcernCategories[] }> = ({ concerns }) => (
/**
* Renders a list of concerns.
*
* @param {Object} props - The properties of the ConcernList component.
* @param {Concern[]} props.concerns - The list of concerns to render.
* @returns {ReactElement} The rendered list of concerns.
*/
const ConcernList: React.FC<{ concerns: Concern[] }> = ({ concerns }) => (
<Stack>
{concerns.map((c) => (
<StackItem key={c.category}>
{statusIcons[c.category]} {c.label}
{getCategoryIcon(c.category)} {c.label}
</StackItem>
))}
</Stack>
);

const ConcernLabel: React.FC<{ category: string; count: number }> = ({ category, count }) => (
<Label variant="outline" color={categoryColors[category]} icon={statusIcons[category]}>
{count}
</Label>
);
/**
* Groups concerns by their category.
*
* @param {Concern[]} concerns - The list of concerns to group.
* @returns {Record<string, Concern[]>} The grouped concerns by category.
*/
const groupConcernsByCategory = (concerns: Concern[] = []): Record<string, Concern[]> => {
return concerns.reduce(
(acc, concern) => {
if (!acc[concern.category]) {
acc[concern.category] = [];
}
acc[concern.category].push(concern);
return acc;
},
{
Critical: [],
Information: [],
Warning: [],
},
);
};

/**
* Retrieves the title for a given concern category.
*
* @param {string} category - The category of the concern.
* @param {TFunction} t - The translation function.
* @returns {string} The title for the given category.
*/
const getCategoryTitle = (category: string, t: TFunction): string => {
const titles = {
Critical: t('Critical concerns'),
Information: t('Information concerns'),
Warning: t('Warning concerns'),
};

const statusIcons = {
Critical: <RedExclamationCircleIcon />,
Information: <BlueInfoCircleIcon />,
Warning: <YellowExclamationTriangleIcon />,
return titles[category] || '';
};

const categoryColors = {
Critical: 'red',
Information: 'blue',
Warning: 'orange',
/**
* Retrieves the icon for a given concern category.
*
* @param {string} category - The category of the concern.
* @returns {ReactElement} The icon for the given category.
*/
const getCategoryIcon = (category: string) => {
const icons = {
Critical: <RedExclamationCircleIcon />,
Information: <BlueInfoCircleIcon />,
Warning: <YellowExclamationTriangleIcon />,
};

return icons[category] || <></>;
};

/**
* Retrieves the color for a given concern category.
*
* @param {string} category - The category of the concern.
* @returns {string} The color for the given category.
*/
const getCategoryColor = (category: string) => {
const colors = {
Critical: 'red',
Information: 'blue',
Warning: 'orange',
};

return colors[category] || 'grey';
};

0 comments on commit 5044244

Please sign in to comment.