Katello/katello

View on GitHub
webpack/scenes/ContentViews/Details/Versions/Compare/CVVersionCompare.js

Summary

Maintainability
A
2 hrs
Test Coverage
import React, { useState, useEffect, useCallback } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
import { translate as __ } from 'foremanReact/common/I18n';
import { STATUS } from 'foremanReact/constants';
import { Tab, Tabs, TabTitleText } from '@patternfly/react-core';
import CVVersionCompareHeader from './CVVersionCompareHeader';
import { selectCVDetails, selectCVVersionDetails, selectCVVersionDetailsStatus } from '../../ContentViewDetailSelectors';
import getCVVersionCompareTableConfigs from './CVVersionCompareConfig';
import CVVersionCompareTable from './CVVersionCompareTable';
import getContentViewDetails, { getContentViewVersionDetails } from '../../ContentViewDetailActions';
import Loading from '../../../../../components/Loading';
import './CVVersionCompare.scss';
import EmptyStateMessage from '../../../../../components/Table/EmptyStateMessage';

const CVVersionCompare = ({
  cvId,
  versionIds,
  versionLabels,
}) => {
  const dispatch = useDispatch();
  const { versionOneId: initialVersionOneId, versionTwoId: initialVersionTwoId } = versionIds;
  const { versionOneLabel: initialVersionOne, versionTwoLabel: initialVersionTwo } = versionLabels;
  const { versions: cvDetails } = useSelector(state => selectCVDetails(state, cvId));
  const [versionOne, setVersionOne] = useState(initialVersionOne);
  const [versionTwo, setVersionTwo] = useState(initialVersionTwo);
  const getIdFromVersion = useCallback(version => (cvDetails?.find(result =>
    Number(result.version) === Number(version))?.id), [cvDetails]);

  const versionOneDetails = useSelector(state =>
    selectCVVersionDetails(state, String(getIdFromVersion(versionOne)
      ?? initialVersionOneId), cvId));
  const versionTwoDetails = useSelector(state =>
    selectCVVersionDetails(state, String(getIdFromVersion(versionTwo)
      ?? initialVersionTwoId), cvId));

  const [selectedViewBy, setSelectedViewBy] = useState('All');
  const tableConfigs = getCVVersionCompareTableConfigs({
    versionOne,
    versionTwo,
    versionOneId: String(getIdFromVersion(versionOne)),
    versionTwoId: String(getIdFromVersion(versionTwo)),
    viewBy: selectedViewBy.toLowerCase(),
  });

  const filteredTableConfigs = tableConfigs.filter(({ getCountKey }) =>
    !!getCountKey(versionOneDetails, versionTwoDetails));
  const versionOneDetailsStatus = useSelector(state =>
    selectCVVersionDetailsStatus(state, String(getIdFromVersion(versionOne)
      ?? initialVersionOneId), cvId));
  const versionTwoDetailsStatus = useSelector(state =>
    selectCVVersionDetailsStatus(state, String(getIdFromVersion(versionTwo)
      ?? initialVersionTwoId), cvId));

  const [currentActiveTab, setCurrentActiveTab] = useState(__('Repositories'));
  const onSelect = (_e, eventKey) => {
    // This prevents needless pushing on repeated clicks of a tab
    if (currentActiveTab !== eventKey) {
      setCurrentActiveTab(eventKey);
    }
  };
  const activeTableConfig = filteredTableConfigs.find(config =>
    String(currentActiveTab) === config.name);
  const showTabs = filteredTableConfigs.length > 0;
  const showCompareTable = !(versionOneDetailsStatus === STATUS.PENDING
    ||
    versionTwoDetailsStatus === STATUS.PENDING) && versionOne && versionTwo;

  useEffect(() => {
    if (!cvDetails) {
      dispatch(getContentViewDetails(cvId));
    }
  }, [dispatch, cvDetails, cvId]);

  useEffect(() => {
    if (cvDetails) {
      dispatch(getContentViewVersionDetails(String(getIdFromVersion(versionOne)
        ?? initialVersionOneId), cvId));
      dispatch(getContentViewVersionDetails(String(getIdFromVersion(versionTwo)
        ?? initialVersionTwoId), cvId));
    }
  }, [dispatch, versionOne, versionTwo, cvId, getIdFromVersion, cvDetails,
    initialVersionOneId, initialVersionTwoId]);

  return (
    <>
      <CVVersionCompareHeader
        versionOne={versionOne}
        versionTwo={versionTwo}
        cvId={cvId}
        setVersionOne={setVersionOne}
        setVersionTwo={setVersionTwo}
        selectedViewBy={selectedViewBy}
        setSelectedViewBy={setSelectedViewBy}
      />
      {showTabs && (
        (showCompareTable &&
          <div className="grid-with-top-border">
            <Tabs
              isVertical
              activeKey={currentActiveTab}
              onSelect={onSelect}
              ouiaId="cv-version-compare-tabs"
            >
              {filteredTableConfigs.map((config) => {
                const { name } = config;
                return (
                  <Tab
                    ouiaId={`cv-version-compare-tab-${name}`}
                    key={name}
                    eventKey={name}
                    title={
                      <>
                        <TabTitleText>{name}</TabTitleText>
                      </>}
                  />
                );
              })}
            </Tabs>
            <div className="compare-table-container">
              <CVVersionCompareTable
                tableConfig={activeTableConfig}
                versionOne={versionOne}
                versionTwo={versionTwo}
                currentActiveKey={currentActiveTab}
                selectedViewBy={selectedViewBy}
              />
            </div>
          </div >) || <Loading />)
      }
      {!showTabs &&
      <EmptyStateMessage
        title={__('Empty content view versions')}
        body={__('No content in selected versions.')}
        search
      />
      }
    </>
  );
};
CVVersionCompare.propTypes = {
  cvId: PropTypes.number.isRequired,
  versionIds: PropTypes.shape({
    versionOneId: PropTypes.string,
    versionTwoId: PropTypes.string,
  }).isRequired,
  versionLabels: PropTypes.shape({
    versionOneLabel: PropTypes.string,
    versionTwoLabel: PropTypes.string,
  }).isRequired,
};
export default CVVersionCompare;