@plone/volto
Version:
Volto
356 lines (346 loc) • 11.5 kB
JSX
/**
* Upgrade controlpanel container.
* @module components/manage/Controlpanels/Upgrade
*/
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { Link } from 'react-router-dom';
import { createPortal } from 'react-dom';
import {
Button,
Container,
Form,
Message,
Segment,
Table,
} from 'semantic-ui-react';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import map from 'lodash/map';
import { getSystemInformation } from '@plone/volto/actions/controlpanels/controlpanels';
import {
getUpgradeInformation,
runUpgrade,
} from '@plone/volto/actions/upgrade/upgrade';
import Helmet from '@plone/volto/helpers/Helmet/Helmet';
import Icon from '@plone/volto/components/theme/Icon/Icon';
import Toast from '@plone/volto/components/manage/Toast/Toast';
import Toolbar from '@plone/volto/components/manage/Toolbar/Toolbar';
import { VersionOverview } from '@plone/volto/components/manage/Controlpanels';
import backSVG from '@plone/volto/icons/back.svg';
import { toast } from 'react-toastify';
const messages = defineMessages({
back: {
id: 'Back',
defaultMessage: 'Back',
},
upgradeInformation: {
id: 'Upgrade Plone Site',
defaultMessage: 'Upgrade Plone Site',
},
upgrade: {
id: 'Upgrade Plone Site',
defaultMessage: 'Upgrade Plone Site',
},
upgradeSuccess: {
id: 'Your site is up to date.',
defaultMessage: 'Your site is up to date.',
},
dryRunSuccess: {
id: 'Dry run selected, transaction aborted.',
defaultMessage: 'Dry run selected, transaction aborted.',
},
upgradeError: {
id: 'There was an error with the upgrade.',
defaultMessage: 'There was an error with the upgrade.',
},
});
const UpgradeStep = ({ title, steps }) => {
const stepTitles = steps.map((step) => {
return step.title;
});
return (
<Message>
<Message.Header>{title}</Message.Header>
<Message.List items={stepTitles} />
</Message>
);
};
/**
* UpgradeControlPanel class.
* @class UpgradeControlPanel
* @extends Component
*/
class UpgradeControlPanel extends Component {
/**
* Property types.
* @property {Object} propTypes Property types.
* @static
*/
static propTypes = {
getUpgradeInformation: PropTypes.func.isRequired,
getSystemInformation: PropTypes.func.isRequired,
runUpgrade: PropTypes.func.isRequired,
};
/**
* Constructor
* @method constructor
* @param {Object} props Component properties
* @constructs DiffComponent
*/
constructor(props) {
super(props);
this.runUpgrade = this.runUpgrade.bind(this);
this.state = {
isClient: false,
dryRun: false,
};
}
/**
* Component did mount
* @method componentDidMount
* @returns {undefined}
*/
componentDidMount() {
this.props.getUpgradeInformation();
this.props.getSystemInformation();
this.setState({ isClient: true, dryRun: false });
}
/**
* Run Upgrade handler
* @method runUpgrade
* @param {boolean} dryRun Id of package to install.
* @returns {undefined}
*/
runUpgrade(dryRun) {
this.props
.runUpgrade(dryRun)
.then(() => {
if (!dryRun) {
// Upgrade completed
this.props.getUpgradeInformation();
toast.success(
<Toast
success
title={this.props.intl.formatMessage(messages.upgrade)}
content={this.props.intl.formatMessage(messages.upgradeSuccess)}
/>,
);
} else {
toast.success(
<Toast
success
title={this.props.intl.formatMessage(messages.upgrade)}
content={this.props.intl.formatMessage(messages.dryRunSuccess)}
/>,
);
}
})
.catch(() => {
toast.error(
<Toast
error
title={this.props.intl.formatMessage(messages.upgrade)}
content={this.props.intl.formatMessage(messages.upgradeError)}
/>,
);
});
}
/**
* Render method.
* @method render
* @returns {string} Markup for the component.
*/
render() {
const upgradeInformation = this.props.upgradeInformation;
const upgradeSteps = upgradeInformation
? Object.entries(upgradeInformation.upgrade_steps)
: null;
return upgradeInformation ? (
<Container id="upgrade-page" className="controlpanel-upgrade">
<Helmet
title={this.props.intl.formatMessage(messages.upgradeInformation)}
/>
<Segment.Group raised>
<Segment className="primary">
<FormattedMessage
id="Upgrade Plone Site"
defaultMessage="Upgrade Plone Site"
/>
</Segment>
<Segment className="secondary">
<FormattedMessage
id="More information about the upgrade procedure can be found in the documentation section of plone.org in the Upgrade Guide."
defaultMessage="More information about the upgrade procedure can be found in the documentation section of plone.org in the Upgrade Guide."
/>
</Segment>
<Message attached>
<Message.Header>
<FormattedMessage
id="Configuration Versions"
defaultMessage="Configuration Versions"
/>
</Message.Header>
</Message>
<Segment>
{upgradeInformation.versions.fs ===
upgradeInformation.versions.instance ? (
<Message attached success>
<FormattedMessage
id="Your site is up to date."
defaultMessage="Your site is up to date."
/>
</Message>
) : (
<Message attached warning>
<FormattedMessage
id="The site configuration is outdated and needs to be upgraded."
defaultMessage="The site configuration is outdated and needs to be upgraded."
/>
</Message>
)}
<Table celled padded columns="2">
<Table.Body>
<Table.Row>
<Table.Cell>
<FormattedMessage
id="Current active configuration"
defaultMessage="Current active configuration"
/>
</Table.Cell>
<Table.Cell>
{upgradeInformation.versions.instance}
</Table.Cell>
</Table.Row>
<Table.Row>
<Table.Cell>
<FormattedMessage
id="Latest available configuration"
defaultMessage="Latest available configuration"
/>
</Table.Cell>
<Table.Cell>{upgradeInformation.versions.fs}</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
</Segment>
{upgradeSteps.length > 0 && (
<>
<Message attached>
<Message.Header>
<FormattedMessage
id="Upgrade Steps"
defaultMessage="Upgrade Steps"
/>
</Message.Header>
<Message.Content>
<FormattedMessage
id="The following list shows which upgrade steps are going to be run. Upgrading sometimes performs a catalog/security update, which may take a long time on large sites. Be patient."
defaultMessage="The following list shows which upgrade steps are going to be run. Upgrading sometimes performs a catalog/security update, which may take a long time on large sites. Be patient."
/>
</Message.Content>
</Message>
<Segment>
<Container>
{map(upgradeSteps, (upgradeGroup) => [
<UpgradeStep
key={upgradeGroup[0]}
title={upgradeGroup[0]}
steps={upgradeGroup[1]}
/>,
])}
</Container>
<Message negative>
<FormattedMessage
id="Please ensure you have a backup of your site before performing the upgrade."
defaultMessage="Please ensure you have a backup of your site before performing the upgrade."
/>
</Message>
<Form.Checkbox
onChange={(e, data) =>
this.setState({ dryRun: data.checked })
}
checked={this.state.dryRun}
label="Dry run mode"
/>
<br />
<Button
aria-label={this.props.intl.formatMessage({
id: 'Upgrade',
defaultMessage: 'Upgrade',
})}
onClick={() => this.runUpgrade(this.state.dryRun)}
primary
>
<FormattedMessage id="Upgrade" defaultMessage="Upgrade" />
</Button>
</Segment>
</>
)}
{this.props.upgradeReport ? (
<>
<Message attached>
<Message.Header>
<FormattedMessage
id="Upgrade Report"
defaultMessage="Upgrade Report"
/>
</Message.Header>
</Message>
<Segment>
<pre>{this.props.upgradeReport.report}</pre>
</Segment>
</>
) : null}
<Message attached>
<Message.Header>
<FormattedMessage
id="Version Overview"
defaultMessage="Version Overview"
/>
</Message.Header>
</Message>
<Segment>
{this.props.systemInformation ? (
<VersionOverview {...this.props.systemInformation} />
) : null}
</Segment>
</Segment.Group>
{this.state.isClient &&
createPortal(
<Toolbar
pathname={this.props.pathname}
hideDefaultViewButtons
inner={
<>
<Link to="/controlpanel" className="item">
<Icon
name={backSVG}
aria-label={this.props.intl.formatMessage(messages.back)}
className="contents circled"
size="30px"
title={this.props.intl.formatMessage(messages.back)}
/>
</Link>
</>
}
/>,
document.getElementById('toolbar'),
)}
</Container>
) : null;
}
}
export default compose(
injectIntl,
connect(
(state, props) => ({
upgradeInformation: state.upgrade.upgradeinformation,
pathname: props.location.pathname,
systemInformation: state.controlpanels.systeminformation,
upgradeReport: state.upgrade.upgradereport,
}),
{ getUpgradeInformation, getSystemInformation, runUpgrade },
),
)(UpgradeControlPanel);