diff --git a/cypress/tests/core/basic/workflow.js b/cypress/tests/core/basic/workflow.js
new file mode 100644
index 0000000000..0a58077af6
--- /dev/null
+++ b/cypress/tests/core/basic/workflow.js
@@ -0,0 +1,25 @@
+describe('workflow Tests', () => {
+ beforeEach(() => {
+ cy.autologin();
+ cy.createContent({
+ contentType: 'Document',
+ contentId: 'my-page',
+ contentTitle: 'My Page',
+ allow_discussion: true,
+ }
+ );
+ cy.visit('/contents');
+ });
+ it('change workflow state recursively', function () {
+ cy.get('tr[aria-label="/my-page"]').within(() => {
+ cy.get('button[class="ui basic icon button"]').click({ multiple: true });
+ })
+ cy.get('button[class="ui button icon item"]').eq(1).click();
+ cy.findByText('Select…').click();
+ cy.findByText('Publish').click();
+ cy.findByTitle('Save').click();
+ cy.get('tr[aria-label="/my-page"]').within(() => {
+ cy.get('td > div').should('contain','Published');
+ })
+ });
+ });
\ No newline at end of file
diff --git a/news/4902.feature b/news/4902.feature
new file mode 100644
index 0000000000..7b9df8bbf2
--- /dev/null
+++ b/news/4902.feature
@@ -0,0 +1 @@
+Refactor workflow -@Tishasoumya-02
\ No newline at end of file
diff --git a/src/components/manage/Workflow/Workflow.jsx b/src/components/manage/Workflow/Workflow.jsx
index adc5a5b579..90996c5a02 100644
--- a/src/components/manage/Workflow/Workflow.jsx
+++ b/src/components/manage/Workflow/Workflow.jsx
@@ -1,22 +1,17 @@
-/**
- * Workflow component.
- * @module components/manage/Workflow/Workflow
- */
-
-import React, { Component, Fragment } from 'react';
+import { useEffect } from 'react';
import PropTypes from 'prop-types';
import { compose } from 'redux';
-import { connect } from 'react-redux';
+import { useDispatch, useSelector, shallowEqual } from 'react-redux';
import { uniqBy } from 'lodash';
import { toast } from 'react-toastify';
-import { defineMessages, injectIntl } from 'react-intl';
+import { defineMessages, useIntl } from 'react-intl';
+
import { FormFieldWrapper, Icon, Toast } from '@plone/volto/components';
import {
flattenToAppURL,
- getCurrentStateMapping,
getWorkflowOptions,
+ getCurrentStateMapping,
} from '@plone/volto/helpers';
-
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
import {
@@ -24,7 +19,6 @@ import {
getWorkflow,
transitionWorkflow,
} from '@plone/volto/actions';
-
import downSVG from '@plone/volto/icons/down-key.svg';
import upSVG from '@plone/volto/icons/up-key.svg';
import checkSVG from '@plone/volto/icons/check.svg';
@@ -165,191 +159,88 @@ const customSelectStyles = {
}),
};
-/**
- * Workflow container class.
- * @class Workflow
- * @extends Component
- */
-class Workflow extends Component {
- /**
- * Property types.
- * @property {Object} propTypes Property types.
- * @static
- */
- static propTypes = {
- getContent: PropTypes.func.isRequired,
- getWorkflow: PropTypes.func.isRequired,
- transitionWorkflow: PropTypes.func.isRequired,
- loaded: PropTypes.bool.isRequired,
- pathname: PropTypes.string.isRequired,
- history: PropTypes.arrayOf(
- PropTypes.shape({
- review_state: PropTypes.string,
- }),
- ),
- transitions: PropTypes.arrayOf(
- PropTypes.shape({
- '@id': PropTypes.string,
- title: PropTypes.string,
- }),
- ),
- };
+function useWorkflow() {
+ const history = useSelector((state) => state.workflow.history, shallowEqual);
+ const transitions = useSelector(
+ (state) => state.workflow.transitions,
+ shallowEqual,
+ );
+ const loaded = useSelector((state) => state.workflow.transition.loaded);
+ const currentStateValue = useSelector(
+ (state) => getCurrentStateMapping(state.workflow.currentState),
+ shallowEqual,
+ );
- /**
- * Default properties
- * @property {Object} defaultProps Default properties.
- * @static
- */
- static defaultProps = {
- history: [],
- transitions: [],
- };
+ return { loaded, history, transitions, currentStateValue };
+}
- componentDidMount() {
- this.props.getWorkflow(this.props.pathname);
- }
+const Workflow = (props) => {
+ const intl = useIntl();
+ const dispatch = useDispatch();
+ const { loaded, transitions, currentStateValue } = useWorkflow();
+ const content = useSelector((state) => state.content?.data, shallowEqual);
+ const { pathname } = props;
- /**
- * Component will receive props
- * @method componentWillReceiveProps
- * @param {Object} nextProps Next properties
- * @returns {undefined}
- */
- UNSAFE_componentWillReceiveProps(nextProps) {
- if (nextProps.pathname !== this.props.pathname) {
- this.props.getWorkflow(nextProps.pathname);
- }
- if (!this.props.loaded && nextProps.loaded) {
- this.props.getWorkflow(nextProps.pathname);
- this.props.getContent(nextProps.pathname);
- }
- }
+ useEffect(() => {
+ dispatch(getWorkflow(pathname));
+ dispatch(getContent(pathname));
+ }, [dispatch, pathname, loaded]);
- /**
- * On transition handler
- * @method transition
- * @param {string} event Event object
- * @returns {undefined}
- */
- transition = (selectedOption) => {
- this.props.transitionWorkflow(flattenToAppURL(selectedOption.url));
+ const transition = (selectedOption) => {
+ dispatch(transitionWorkflow(flattenToAppURL(selectedOption.url)));
toast.success(
,
);
};
- selectValue = (option) => {
- const stateDecorator = {
- marginLeft: '10px',
- marginRight: '10px',
- display: 'inline-block',
- backgroundColor: option.color || null,
- content: ' ',
- height: '10px',
- width: '10px',
- borderRadius: '50%',
- };
- return (
-
-
- {option.label}
-
- );
- };
-
- optionRenderer = (option) => {
- const stateDecorator = {
- marginLeft: '10px',
- marginRight: '10px',
- display: 'inline-block',
- backgroundColor:
- this.props.currentStateValue.value === option.value
- ? option.color
- : null,
- content: ' ',
- height: '10px',
- width: '10px',
- borderRadius: '50%',
- border:
- this.props.currentStateValue.value !== option.value
- ? `1px solid ${option.color}`
- : null,
- };
-
- return (
-
-
- {option.label}
-
-
- );
- };
+ const { Placeholder } = props.reactSelect.components;
+ const Select = props.reactSelect.default;
- render() {
- const { Placeholder } = this.props.reactSelect.components;
- const Select = this.props.reactSelect.default;
+ return (
+
+
+ );
+};
- return (
-
-
- );
- }
-}
+Workflow.propTypes = {
+ pathname: PropTypes.string.isRequired,
+};
-export default compose(
- injectIntl,
- injectLazyLibs(['reactSelect']),
- connect(
- (state) => ({
- loaded: state.workflow.transition.loaded,
- content: state.content.data,
- history: state.workflow.history,
- transitions: state.workflow.transitions,
- currentStateValue: getCurrentStateMapping(state.workflow.currentState),
- }),
- { getContent, getWorkflow, transitionWorkflow },
- ),
-)(Workflow);
+export default compose(injectLazyLibs(['reactSelect']))(Workflow);