Project

General

Profile

Download (13.8 KB) Statistics
| Branch: | Tag: | Revision:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Grid, Col, Row, Tabs, Tab, FormControl, ControlLabel } from 'react-bootstrap';
import { FormattedMessage } from 'react-intl';
import { Button, Spinner } from 'patternfly-react';
import { Alert } from '@patternfly/react-core';
import { propsToCamelCase } from 'foremanReact/common/helpers';
import ForemanModal from 'foremanReact/components/ForemanModal';
import Slot from 'foremanReact/components/common/Slot';
import { translate as __ } from 'foremanReact/common/I18n';
import TooltipButton from '../../../components/TooltipButton';
import { LoadingState } from '../../../components/LoadingState';
import { Table } from '../../../components/pf3Table';

import { columns } from './ManifestHistoryTableSchema';
import DeleteManifestModalText from './DeleteManifestModalText';
import { MANAGE_MANIFEST_MODAL_ID, DELETE_MANIFEST_MODAL_ID } from './ManifestConstants';
import { CONTENT_CREDENTIAL_CERT_TYPE } from '../../ContentCredentials/ContentCredentialConstants';
import CdnConfigurationForm from './CdnConfigurationTab';

import './ManageManifestModal.scss';

class ManageManifestModal extends Component {
componentDidMount() {
this.props.loadManifestHistory();
this.props.getContentCredentials({ content_type: CONTENT_CREDENTIAL_CERT_TYPE });
}

componentDidUpdate(prevProps) {
if (!prevProps.taskInProgress && this.props.taskInProgress) {
this.hideModal();
}

if (prevProps.taskInProgress && !this.props.taskInProgress) {
this.props.loadOrganization();
this.props.loadManifestHistory();
}

if (!prevProps.manifestActionStarted && this.props.manifestActionStarted) {
this.hideDeleteManifestModal();
}
}

hideModal = () => {
this.props.setModalClosed({ id: MANAGE_MANIFEST_MODAL_ID });
};

showDeleteManifestModal = () =>
this.props.setModalOpen({ id: DELETE_MANIFEST_MODAL_ID });

hideDeleteManifestModal = () => {
if (this.props.deleteManifestModalExists) {
this.props.setModalClosed({ id: DELETE_MANIFEST_MODAL_ID });
}
};

reloadOrganization = () => {
this.props.loadOrganization();
}

uploadManifest = (fileList) => {
if (fileList.length > 0) {
this.props.upload(fileList[0]);
}
};

refreshManifest = () => {
this.props.refresh();
};

deleteManifest = () => {
this.props.delete();
};

disabledTooltipText = () => {
if (this.props.taskInProgress) {
return __('This is disabled because a manifest task is in progress');
}
return __('This is disabled because no manifest exists');
};

render() {
const {
manifestHistory,
organization,
disableManifestActions,
disabledReason,
canImportManifest,
canDeleteManifest,
simpleContentAccess,
isManifestImported,
canEditOrganizations,
taskInProgress,
manifestActionStarted,
contentCredentials,
} = this.props;

const {
manifestExpiringSoon,
manifestExpired,
manifestExpirationDate,
manifestExpireDaysRemaining,
} = propsToCamelCase(organization);

const actionInProgress = (taskInProgress || manifestActionStarted);
const showCdnConfigurationTab = canEditOrganizations;
const showSubscriptionManifest = (canImportManifest || canDeleteManifest);
const showManifestTab = (canEditOrganizations || showSubscriptionManifest);

const emptyStateData = () => ({
header: __('There is no manifest history to display.'),
description: __('Import a manifest using the Manifest tab above.'),
documentation: {
label: __('Learn more about adding subscription manifests '),
url: 'https://access.redhat.com/solutions/3410771',
},
});

const getManifestName = () => {
let name = __('No manifest imported');

if (
organization.owner_details &&
organization.owner_details.upstreamConsumer
) {
const link = [
'https://',
organization.owner_details.upstreamConsumer.webUrl,
organization.owner_details.upstreamConsumer.uuid,
].join('/');

name = (
<a href={link}>{organization.owner_details.upstreamConsumer.name}</a>
);
}

return name;
};

return (
<ForemanModal id={MANAGE_MANIFEST_MODAL_ID} title={__('Manage Manifest')}>
<Tabs id="manifest-history-tabs">
{showManifestTab &&
<Tab
eventKey={1}
title={__('Manifest')}
>
{showSubscriptionManifest &&
<React.Fragment>
<Grid>
<h3>{__('Subscription Manifest')}</h3>
{manifestExpiringSoon &&
<Alert
ouiaId="manifest-expiring-soon-alert"
variant="warning"
title={__('Manifest expiring soon')}
>
<FormattedMessage
defaultMessage={__('Your manifest will expire in {daysMessage}. To extend the expiration date, refresh your manifest. Or, if your Foreman is disconnected, import a new manifest.')}
values={{
daysMessage: (
<FormattedMessage
defaultMessage="{daysRemaining, plural, one {{singular}} other {# {plural}}}"
values={{
daysRemaining: manifestExpireDaysRemaining,
singular: __('day'),
plural: __('days'),
}}
id="manage-manifest-expire-days-i18n"
/>
),
}}
id="manage-manifest-expire-i18n"
/>
</Alert>
}
{manifestExpired &&
<Alert
ouiaId="manifest-expired-alert"
variant="danger"
title={__('Manifest expired')}
>
<FormattedMessage
defaultMessage={__('Your manifest expired on {expirationDate}. To continue using Red Hat content, import a new manifest.')}
values={{
expirationDate: new Date(manifestExpirationDate).toDateString(),
}}
id="manage-manifest-expired-i18n"
/>
</Alert>
}
<hr />
<Row>
<Col sm={5}>
<strong>{__('Manifest')}</strong>
</Col>
<Col sm={7}>
{getManifestName()}
</Col>
</Row>
{isManifestImported &&
<Row>
<Col sm={5} />
<Col sm={7}>
{manifestExpired ? __('Expired ') : __('Expires ')}
{new Date(manifestExpirationDate).toDateString()}
</Col>
</Row>
}
<Row>
<Col sm={5}>
{canImportManifest &&
<ControlLabel
style={{ paddingTop: '10px' }}
>
<div>{__('Import new manifest')}</div>
</ControlLabel>
}
</Col>
<Col sm={7} className="manifest-actions">
<Spinner loading={actionInProgress} />
{canImportManifest &&
<FormControl
id="usmaFile"
type="file"
accept=".zip"
disabled={actionInProgress}
onChange={e => this.uploadManifest(e.target.files)}
/>
}
<div id="manifest-actions-row">
{canImportManifest &&
<TooltipButton
onClick={this.refreshManifest}
tooltipId="refresh-manifest-button-tooltip"
tooltipText={disabledReason}
tooltipPlacement="top"
title={__('Refresh')}
disabled={!isManifestImported ||
actionInProgress || disableManifestActions}
/>
}
{canDeleteManifest &&
<React.Fragment>
<TooltipButton
disabled={!isManifestImported || actionInProgress}
bsStyle="danger"
onClick={this.showDeleteManifestModal}
title={__('Delete')}
tooltipId="delete-manifest-button-tooltip"
tooltipText={this.disabledTooltipText()}
tooltipPlacement="top"
/>
</React.Fragment>
}
</div>
<ForemanModal title={__('Confirm delete manifest')} id={DELETE_MANIFEST_MODAL_ID}>
<DeleteManifestModalText simpleContentAccess={simpleContentAccess} />
<ForemanModal.Footer>
<Button bsStyle="default" onClick={this.hideDeleteManifestModal}>
{__('Cancel')}
</Button>
<Button bsStyle="danger" onClick={this.deleteManifest}>
{__('Delete')}
</Button>
</ForemanModal.Footer>
</ForemanModal>
</Col>
</Row>
</Grid>
</React.Fragment>
}
<Slot id="katello-manage-manifest-form" multi />
</Tab>
}
<Tab
eventKey={2}
title={__('Manifest History')}
>
<LoadingState loading={manifestHistory.loading} loadingText={__('Loading')}>
<Table
rows={manifestHistory.results}
columns={columns}
emptyState={emptyStateData()}
/>
</LoadingState>
</Tab>
{showCdnConfigurationTab &&
<Tab
eventKey={3}
title={__('CDN Configuration')}
>
<Grid>
<h3>{__('CDN Configuration for Red Hat Content')}</h3>
<hr />
<CdnConfigurationForm
cdnConfiguration={organization.cdn_configuration}
contentCredentials={contentCredentials}
onUpdate={this.reloadOrganization}
/>
</Grid>
</Tab>
}
</Tabs>
<ForemanModal.Footer>
<Button bsStyle="primary" onClick={this.hideModal}>
{__('Close')}
</Button>
</ForemanModal.Footer>
</ForemanModal>
);
}
}

ManageManifestModal.propTypes = {
upload: PropTypes.func.isRequired,
refresh: PropTypes.func.isRequired,
delete: PropTypes.func.isRequired,
loadManifestHistory: PropTypes.func.isRequired,
getContentCredentials: PropTypes.func.isRequired,
organization: PropTypes.shape({
id: PropTypes.number,
loading: PropTypes.bool,
cdn_configuration: PropTypes.shape({
url: PropTypes.string,
username: PropTypes.string,
upstream_organization_label: PropTypes.string,
ssl_ca_credential_id: PropTypes.number,
password_exists: PropTypes.bool,
}),
owner_details: PropTypes.shape({
upstreamConsumer: PropTypes.shape({
uuid: PropTypes.string,
name: PropTypes.string,
webUrl: PropTypes.string,
}),
}),
}).isRequired,
canImportManifest: PropTypes.bool,
canDeleteManifest: PropTypes.bool,
simpleContentAccess: PropTypes.bool,
isManifestImported: PropTypes.bool,
deleteManifestModalExists: PropTypes.bool,
canEditOrganizations: PropTypes.bool,
disableManifestActions: PropTypes.bool,
disabledReason: PropTypes.string,
loadOrganization: PropTypes.func.isRequired,
taskInProgress: PropTypes.bool.isRequired,
manifestHistory: PropTypes.shape({
loading: PropTypes.bool,
// Disabling rule as existing code failed due to an eslint-plugin-react update
// eslint-disable-next-line react/forbid-prop-types
results: PropTypes.array,
}).isRequired,
setModalClosed: PropTypes.func.isRequired,
setModalOpen: PropTypes.func.isRequired,
manifestActionStarted: PropTypes.bool,
contentCredentials: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.number,
name: PropTypes.string,
})),
};

ManageManifestModal.defaultProps = {
disableManifestActions: false,
disabledReason: '',
canImportManifest: false,
canDeleteManifest: false,
simpleContentAccess: true,
isManifestImported: false,
deleteManifestModalExists: false,
canEditOrganizations: false,
manifestActionStarted: false,
contentCredentials: [],
};

export default ManageManifestModal;
(2-2/8)