Project

General

Profile

Download (7.95 KB) Statistics
| Branch: | Tag: | Revision:
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import { Modal, Button, Alert, TextContent, Text, TextVariants } from '@patternfly/react-core';
import { translate as __ } from 'foremanReact/common/I18n';
import { STATUS } from 'foremanReact/constants';
import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
import { selectAPIStatus } from 'foremanReact/redux/API/APISelectors';
import { ENVIRONMENT_PATHS_KEY } from '../../../../../scenes/ContentViews/components/EnvironmentPaths/EnvironmentPathConstants';
import EnvironmentPaths from '../../../../../scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths';
import ContentViewSelect from '../../../../../scenes/ContentViews/components/ContentViewSelect/ContentViewSelect';
import ContentViewSelectOption from '../../../../../scenes/ContentViews/components/ContentViewSelect/ContentViewSelectOption';
import api from '../../../../../services/api';
import getContentViews from '../../../../../scenes/ContentViews/ContentViewsActions';
import { selectContentViews, selectContentViewStatus } from '../../../../../scenes/ContentViews/ContentViewSelectors';
import { bulkUpdateHostContentViewAndEnvironment } from './actions';
import { getCVPlaceholderText } from '../../../../../scenes/ContentViews/components/ContentViewSelect/helpers';
import HOST_CV_AND_ENV_KEY from '../../../HostDetails/Cards/ContentViewDetailsCard/HostContentViewConstants';

const ENV_PATH_OPTIONS = { key: ENVIRONMENT_PATHS_KEY };

const BulkChangeHostCVModal = ({
isOpen,
closeModal,
selectedCount,
orgId,
fetchBulkParams,
}) => {
const [selectedLifecycleEnv, setSelectedLifecycleEnv]
= useState([]);

const [selectedContentView, setSelectedContentView] = useState(null);
const [cvSelectOpen, setCVSelectOpen] = useState(false);
const dispatch = useDispatch();
const contentViewsInEnvResponse = useSelector(state => selectContentViews(state, '_FOR_DEFAULT_ENV'));
const { results } = contentViewsInEnvResponse;
const contentViewsInEnvStatus = useSelector(state => selectContentViewStatus(state, '_FOR_DEFAULT_ENV'));
const hostUpdateStatus = useSelector(state => selectAPIStatus(state, HOST_CV_AND_ENV_KEY));
const pathsUrl = `/organizations/${orgId}/environments/paths?permission_type=promotable`;
useAPI( // No TableWrapper here, so we can useAPI from Foreman
'get',
api.getApiUrl(pathsUrl),
ENV_PATH_OPTIONS,
);
const selectedContentViewId = results?.find(cv => cv.name === selectedContentView)?.id;

const handleModalClose = () => {
setCVSelectOpen(false);
setSelectedContentView(null);
setSelectedLifecycleEnv([]);
closeModal();
};

const selectedEnv = selectedLifecycleEnv?.[0];
const selectedEnvId = selectedEnv?.id;

const handleCVSelect = (event, selection) => {
setSelectedContentView(selection);
setCVSelectOpen(false);
};

const handleEnvSelect = (selection) => {
dispatch(getContentViews({
environment_id: selection[0].id,
include_default: true,
full_result: true,
order: 'default DESC', // show Default Organization View first
}, '_FOR_DEFAULT_ENV'));
setSelectedContentView(null);
setSelectedLifecycleEnv(selection);
};
const { results: contentViewsInEnv = [] } = contentViewsInEnvResponse;
const canSave = !!(selectedContentView && selectedLifecycleEnv.length);

const handleSave = () => {
const requestBody = {
content_view_id: selectedContentViewId,
environment_id: selectedEnvId,
organization_id: orgId,
included: {
search: fetchBulkParams(),
},
};
dispatch(bulkUpdateHostContentViewAndEnvironment(
requestBody, fetchBulkParams(),
handleModalClose, handleModalClose,
));
};

const cvPlaceholderText = getCVPlaceholderText({
environments: selectedLifecycleEnv,
cvSelectOptions: contentViewsInEnv,
contentViewsStatus: contentViewsInEnvStatus,
});

const stillLoading =
(contentViewsInEnvStatus === STATUS.PENDING || hostUpdateStatus === STATUS.PENDING);
const noContentViewsAvailable =
(contentViewsInEnv.length === 0 || selectedLifecycleEnv.length === 0);

const modalActions = ([
<Button
key="add"
ouiaId="bulk-change-host-cv-modal-add-button"
variant="primary"
onClick={handleSave}
isDisabled={!canSave || hostUpdateStatus === STATUS.PENDING}
isLoading={hostUpdateStatus === STATUS.PENDING}
>
{__('Save')}
</Button>,
<Button key="cancel" ouiaId="change-host-cv-modal-cancel-button" variant="link" onClick={handleModalClose}>
Cancel
</Button>,
]);
return (
<Modal
isOpen={isOpen}
onClose={handleModalClose}
onEscapePress={handleModalClose}
title={__('Edit content view environments')}
width="50%"
position="top"
actions={modalActions}
id="bulk-change-host-cv-modal"
key="bulk-change-host-cv-modal"
ouiaId="bulk-change-host-cv-modal"
>
<TextContent>
<Text
ouiaId="bulk-change-cv-options-description"
>
<FormattedMessage
defaultMessage={__('This will update the content view environments for {hosts}.')}
values={{
hosts: (
<strong>
<FormattedMessage
defaultMessage="{count, plural, one {# {singular}} other {# {plural}}}"
values={{
count: selectedCount,
singular: __('selected host'),
plural: __('selected hosts'),
}}
id="ccs-options-i18n"
/>
</strong>
),
}}
id="bulk-change-cv-options-description-i18n"
/>
</Text>
</TextContent>
{contentViewsInEnvStatus === STATUS.RESOLVED &&
!!selectedLifecycleEnv.length && contentViewsInEnv.length === 0 &&
<Alert
ouiaId="no-cv-alert"
variant="warning"
isInline
title={__('No content views available for the selected environment')}
style={{ marginBottom: '1rem' }}
>
<a href="/content_views">{__('View the Content Views page')}</a>
{__(' to manage and promote content views, or select a different environment.')}
</Alert>
}
<EnvironmentPaths
userCheckedItems={selectedLifecycleEnv}
setUserCheckedItems={handleEnvSelect}
publishing={false}
multiSelect={false}
headerText={__('Select environment')}
isDisabled={hostUpdateStatus === STATUS.PENDING}
/>
<ContentViewSelect
selections={selectedContentView}
onClear={() => setSelectedContentView(null)}
onSelect={handleCVSelect}
isOpen={cvSelectOpen}
isDisabled={stillLoading || noContentViewsAvailable}
onToggle={isExpanded => setCVSelectOpen(isExpanded)}
placeholderText={cvPlaceholderText}
>
{(contentViewsInEnv.length !== 0 && selectedLifecycleEnv.length !== 0) &&
contentViewsInEnv?.map(cv => (
<ContentViewSelectOption
key={cv.id}
value={cv.name}
cv={cv}
env={selectedLifecycleEnv[0]}
/>
))}
</ContentViewSelect>
<hr />
<TextContent>
<Text component={TextVariants.small} ouiaId="profile-upload-reminder-text">
{__('Errata and package information will be updated at the next host check-in or package action.')}
</Text>
</TextContent>
<hr />
</Modal>
);
};

BulkChangeHostCVModal.propTypes = {
isOpen: PropTypes.bool,
closeModal: PropTypes.func,
selectedCount: PropTypes.number.isRequired,
orgId: PropTypes.number.isRequired,
fetchBulkParams: PropTypes.func.isRequired,
};

BulkChangeHostCVModal.defaultProps = {
isOpen: false,
closeModal: () => {},
};


export default BulkChangeHostCVModal;
(1-1/3)