Katello/katello

View on GitHub
webpack/components/extensions/HostDetails/Cards/SystemPurposeCard/SystemPurposeCard.js

Summary

Maintainability
B
4 hrs
Test Coverage
import React, { useState } from 'react';
import { useSelector } from 'react-redux';
import PropTypes from 'prop-types';
import { STATUS } from 'foremanReact/constants';
import { selectAPIStatus } from 'foremanReact/redux/API/APISelectors';
import {
  Button,
  Card,
  CardHeader,
  CardTitle,
  CardBody,
  DescriptionList,
  DescriptionListGroup,
  DescriptionListDescription as Dd,
  DescriptionListTerm as Dt,
  Flex,
  FlexItem,
  GridItem,
  Label,
  List,
  ListItem,
  Tooltip,
  Skeleton,
  CardExpandableContent,
} from '@patternfly/react-core';
import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
import { translate as __ } from 'foremanReact/common/I18n';
import { propsToCamelCase } from 'foremanReact/common/helpers';
import './SystemPurposeCard.scss';
import SystemPurposeEditModal from './SystemPurposeEditModal';
import { selectHostDetailsStatus } from '../../HostDetailsSelectors';
import { hasRequiredPermissions, hostIsNotRegistered } from '../../hostDetailsHelpers';

const SystemPurposeCard = ({ hostDetails, akDetails }) => {
  const sysPurposeCardType = hostDetails?.id ? 'host' : 'ak';
  const isAKType = sysPurposeCardType === 'ak';
  const isHostType = sysPurposeCardType === 'host';
  const details = isHostType ? hostDetails : akDetails;
  const requiredPermission = isHostType ? 'edit_hosts' : 'edit_activation_keys';
  const showEditButton = hasRequiredPermissions([requiredPermission], details?.permissions);
  const { organization_id: orgId, name } = details;
  const subscriptionFacetAttributes = details?.subscription_facet_attributes;
  const {
    purposeRole, purposeUsage, purposeAddons, releaseVersion, serviceLevel,
  } = propsToCamelCase((subscriptionFacetAttributes || details) ?? {});
  const sysPurposeProps = {
    purposeRole,
    purposeUsage,
    purposeAddons,
    releaseVersion,
    serviceLevel,
  };
  const selectAKDetailsStatus = state =>
    selectAPIStatus(state, `ACTIVATION_KEY_${details.id}`) ?? STATUS.PENDING;

  const statusSelector = isHostType ? selectHostDetailsStatus : selectAKDetailsStatus;
  const detailsStatus = useSelector(statusSelector);
  const dataIsLoading = detailsStatus === STATUS.PENDING;

  const [editing, setEditing] = useState(false);

  const [isExpanded, setIsExpanded] = React.useState(true);

  const onExpand = () => {
    setIsExpanded(!isExpanded);
  };
  const cardHeaderProps = {
    toggleButtonProps: { id: 'sys-purpose-toggle', 'aria-label': 'sys-purpose-toggle' },
  };
  if (isAKType) cardHeaderProps.onExpand = onExpand;

  if (!details?.id) {
    return (
      <GridItem rowSpan={1} md={6} lg={4} xl2={3}>
        <Card ouiaId="system-purpose-card">
          <Skeleton />
        </Card>
      </GridItem>
    );
  }

  if (isHostType && hostIsNotRegistered({ hostDetails: details })) return null;
  return (
    <GridItem rowSpan={1} md={6} lg={4} xl2={3}>
      <Card ouiaId="system-purpose-card" id="system-purpose-card" isExpanded={isHostType ? true : isExpanded}>
        <CardHeader {...cardHeaderProps}>
          <Flex
            alignItems={{ default: 'alignItemsCenter' }}
            justifyContent={{ default: 'justifyContentSpaceBetween' }}
            style={{ width: '100%' }}
          >
            <FlexItem>
              <Flex
                alignItems={{ default: 'alignItemsCenter' }}
                justifyContent={{ default: 'justifyContentSpaceBetween' }}
              >
                <FlexItem style={{ marginRight: '0.5em' }}>
                  <CardTitle>{__('System purpose')}</CardTitle>
                </FlexItem>
                <FlexItem>
                  <Tooltip
                    content={__('System purpose enables you to set the system\'s intended use on your network and improves reporting accuracy in the Subscriptions service of the Red Hat Hybrid Cloud Console.')}
                    position="top"
                    enableFlip
                    isContentLeftAligned
                  >
                    <OutlinedQuestionCircleIcon style={{ marginTop: '7px' }} color="gray" />
                  </Tooltip>
                </FlexItem>
              </Flex>
            </FlexItem>
            {showEditButton && (
              <FlexItem>
                <Button variant="link" isSmall ouiaId="syspurpose-edit-button" onClick={() => setEditing(val => !val)}>{__('Edit')}</Button>
              </FlexItem>)
            }
          </Flex>
        </CardHeader>
        <CardExpandableContent>
          <CardBody className="system-purpose-card-body">
            <DescriptionList isHorizontal columnModifier={isAKType ? { default: '2Col' } : undefined}>
              <DescriptionListGroup>
                <Dt>{__('Role')}</Dt>
                <Dd>
                  {dataIsLoading ? <Skeleton /> : purposeRole}
                </Dd>
                <Dt>{__('SLA')}</Dt>
                <Dd>
                  {serviceLevel && (dataIsLoading ? <Skeleton /> : (
                    <Label color="blue">{serviceLevel}</Label>
                  ))}
                </Dd>
              </DescriptionListGroup>
              <DescriptionListGroup>
                <Dt>{__('Usage type')}</Dt>
                <Dd>
                  {purposeUsage && (dataIsLoading ? <Skeleton /> : (
                    <Label color="blue">{purposeUsage}</Label>
                  ))}
                </Dd>
                <Dt>{__('Release version')}</Dt>
                <Dd>
                  {dataIsLoading ? <Skeleton /> : releaseVersion}
                </Dd>
                {!!purposeAddons?.length && (
                  <>
                    <Dt>{__('Add-ons')}</Dt>
                    {dataIsLoading ? <Skeleton /> : (
                      <Dd>
                        <List isPlain>
                          {purposeAddons.map(addon => (
                            <ListItem key={addon}>{addon}</ListItem>
                          ))}
                        </List>
                      </Dd>
                    )}
                  </>
                )
                }
              </DescriptionListGroup>
            </DescriptionList>
            {showEditButton && (
              <SystemPurposeEditModal
                key={name}
                isOpen={editing}
                orgId={orgId}
                closeModal={() => setEditing(false)}
                name={name}
                id={details.id}
                {...sysPurposeProps}
                type={sysPurposeCardType}
              />
            )}
          </CardBody>
        </CardExpandableContent>
      </Card>
    </GridItem>
  );
};

SystemPurposeCard.propTypes = {
  hostDetails: PropTypes.shape({
    name: PropTypes.string,
    organization_id: PropTypes.number,
    id: PropTypes.number,
    subscription_facet_attributes: PropTypes.shape({
      installed_products: PropTypes.arrayOf(PropTypes.shape({
        productId: PropTypes.string,
        productName: PropTypes.string,
      })),
    }),
    permissions: PropTypes.shape({
      edit_hosts: PropTypes.bool,
    }),
  }),
  akDetails: PropTypes.shape({
    name: PropTypes.string,
    organization_id: PropTypes.number,
    id: PropTypes.number,
    purpose_usage: PropTypes.string,
    purpose_role: PropTypes.string,
    release_version: PropTypes.string,
    service_level: PropTypes.string,
    purpose_addons: PropTypes.arrayOf(PropTypes.string),
    permissions: PropTypes.shape({
      edit_activation_keys: PropTypes.bool,
    }),
  }),
};

SystemPurposeCard.defaultProps = {
  hostDetails: {},
  akDetails: {},
};

export default SystemPurposeCard;