import React, { useState, useMemo, useCallback } from 'react'; import useDeepCompareEffect from 'use-deep-compare-effect'; import { useDispatch, useSelector } from 'react-redux'; import { Redirect } from 'react-router-dom'; import { STATUS } from 'foremanReact/constants'; import PropTypes from 'prop-types'; import { Form, FormGroup, TextArea, ActionGroup, Button, Modal, ModalVariant, Alert, TextContent, AlertActionCloseButton, } from '@patternfly/react-core'; import { translate as __ } from 'foremanReact/common/I18n'; import { selectEnvironmentPaths, selectEnvironmentPathsStatus, } from '../../components/EnvironmentPaths/EnvironmentPathSelectors'; import EnvironmentPaths from '../../components/EnvironmentPaths/EnvironmentPaths'; import { getContentViewVersions, promoteContentViewVersion } from '../ContentViewDetailActions'; import { selectPromoteCVVersionError, selectPromoteCVVersionResponse, selectPromoteCVVersionStatus, } from './ContentViewVersionPromoteSelectors'; import ComponentEnvironments from '../ComponentContentViews/ComponentEnvironments'; import Loading from '../../../../components/Loading'; import getContentViews from '../../ContentViewsActions'; const ContentViewVersionPromote = ({ cvId, versionIdToPromote, versionNameToPromote, versionEnvironments, setIsOpen, detailsPage, }) => { const [description, setDescription] = useState(''); const [userCheckedItems, setUserCheckedItems] = useState([]); const [alertDismissed, setAlertDismissed] = useState(false); const [loading, setLoading] = useState(false); const [forcePromote, setForcePromote] = useState([]); const [redirect, setRedirect] = useState(false); const environmentPathResponse = useSelector(selectEnvironmentPaths); const environmentPathStatus = useSelector(selectEnvironmentPathsStatus); const environmentPathLoading = environmentPathStatus === STATUS.PENDING; const promoteResponse = useSelector(state => selectPromoteCVVersionResponse(state, versionIdToPromote, versionEnvironments)); const promoteStatus = useSelector(state => selectPromoteCVVersionStatus(state, versionIdToPromote, versionEnvironments)); const promoteError = useSelector(state => selectPromoteCVVersionError(state, versionIdToPromote, versionEnvironments)); const promoteResolved = promoteStatus === STATUS.RESOLVED; const dispatch = useDispatch(); const onPromote = () => { setLoading(true); dispatch(promoteContentViewVersion({ id: versionIdToPromote, description, versionEnvironments, environment_ids: userCheckedItems.map(item => item.id), force: true, }, () => dispatch(getContentViews()))); }; useDeepCompareEffect(() => { if (promoteResolved && promoteResponse) { dispatch(getContentViewVersions(cvId)); if (detailsPage) { setRedirect(true); } else { setIsOpen(false); } } if (promoteError) { setLoading(false); setIsOpen(false); } }, [promoteResponse, promoteResolved, promoteError, detailsPage, setRedirect, setLoading, setIsOpen, dispatch, cvId]); const envPathFlat = useMemo(() => { if (!environmentPathLoading) { const { results } = environmentPathResponse || {}; return results.map(result => result.environments).flatten(); } return []; }, [environmentPathResponse, environmentPathLoading]); const prior = useCallback( env => envPathFlat.find(item => item.id === env.prior.id), [envPathFlat], ); const isChecked = useCallback( env => (userCheckedItems.includes(env) || versionEnvironments.filter(item => item.id === env.id).length), [userCheckedItems, versionEnvironments], ); const isValid = useCallback((env) => { if (!env.prior || versionEnvironments.some(item => item.id === env.prior.id)) return true; if (!isChecked(prior(env))) return false; return isValid(prior(env)); }, [prior, isChecked, versionEnvironments]); useDeepCompareEffect(() => { setForcePromote(userCheckedItems.filter(item => !isValid(item))); }, [userCheckedItems, setForcePromote, isValid]); const submitDisabled = loading || userCheckedItems.length === 0; if (redirect && detailsPage) { return (); } return ( { setIsOpen(false); }} appendTo={document.body} > {loading ? :
{ e.preventDefault(); onPromote(); }} >