From 4e3a45fa933aa4b96bbcc54c65bdcbba9dc32574 Mon Sep 17 00:00:00 2001 From: shamalka Date: Thu, 4 Jun 2020 10:41:09 +0530 Subject: [PATCH] Improve lifecycle changing UX --- .../react-app/public/conf/config.json | 44 ++++-- .../Release/components/LifeCycle/index.js | 129 +++++++++++------- 2 files changed, 116 insertions(+), 57 deletions(-) diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/public/conf/config.json b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/public/conf/config.json index e6c00f0849..5c74935a80 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/public/conf/config.json +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/public/conf/config.json @@ -40,28 +40,52 @@ }, "lifecycle": { "CREATED": { - "text": "The initial most state of an application." + "title": "Created", + "text": "The initial most state of an application.\n You can only proceed to one of the following states:", + "icon": "file-text", + "step": 0 }, "IN-REVIEW": { - "text": "This state can be applied when the application is being reviewed by approvers." + "title": "In-Review", + "text": "This state can be applied when the application is being reviewed by approvers.\n You can only proceed to one of the following states:", + "icon": "audit", + "step": 1 }, "APPROVED": { - "text": "The approved state is a compulsory state prior to publishing the application." - }, - "REJECTED": { - "text": "The Approvers can reject an application due to a faulty of the app or not being in compliance with company policies." + "title": "Approved", + "text": "The approved state is a compulsory state prior to publishing the application.\n You can only proceed to one of the following states:", + "icon": "file-done", + "step": 2 }, "PUBLISHED": { - "text": "The state which is applied for applications which are qualified for your Corporate App Store. Only the applications of Published state can be installed to your corporate devices." + "title": "Published", + "text": "The state which is applied for applications which are qualified for your Corporate App Store. Only the applications of Published state can be installed to your corporate devices.\n You can only proceed to one of the following states:", + "icon": "global", + "step": 3 }, "BLOCKED": { - "text": "This state allows you to block your application either to publish or deprecate at a future date." + "title": "Blocked", + "text": "This state allows you to block your application either to publish or deprecate at a future date.\n You can only proceed to one of the following states:", + "icon": "exception", + "step": 4 }, "DEPRECATED": { - "text": "The applications which are outdated and no longer suit your app store." + "title": "Deprecated", + "text": "The applications which are outdated and no longer suit your app store.\n You can only proceed to one of the following states:", + "icon": "file-excel", + "step": 5 + }, + "REJECTED": { + "title": "Rejected", + "text": "The Approvers can reject an application due to a faulty of the app or not being in compliance with company policies.\n You can only proceed to one of the following states:", + "icon": "frown", + "step": 6 }, "RETIRED": { - "text": "The final state of an application, where no transition of states will be allowed after this." + "title": "Retired", + "text": "The final state of an application, where no transition of states will be allowed after this.\n You can only proceed to one of the following states:", + "icon": "rest", + "step": 7 } }, "deviceTypes": { diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/scenes/Release/components/LifeCycle/index.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/scenes/Release/components/LifeCycle/index.js index 1ac3deb866..ba6227af87 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/scenes/Release/components/LifeCycle/index.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/scenes/Release/components/LifeCycle/index.js @@ -21,21 +21,21 @@ import { Typography, Tag, Divider, - Select, Button, Modal, notification, + Steps, + Icon, + Alert, } from 'antd'; import axios from 'axios'; import ReactQuill from 'react-quill'; import 'react-quill/dist/quill.snow.css'; import './styles.css'; -import LifeCycleDetailsModal from './components/lifeCycleDetailsModal'; import { withConfigContext } from '../../../../../../../../components/ConfigContext'; import { handleApiError } from '../../../../../../../../services/utils/errorHandler'; const { Text, Title, Paragraph } = Typography; -const { Option } = Select; const modules = { toolbar: [ @@ -60,6 +60,8 @@ const formats = [ 'image', ]; +const { Step } = Steps; + class LifeCycle extends React.Component { constructor(props) { super(props); @@ -69,9 +71,23 @@ class LifeCycle extends React.Component { reasonText: '', isReasonModalVisible: false, isConfirmButtonLoading: false, + current: 0, + lifecycleSteps: [], }; } + componentDidMount() { + const config = this.props.context; + const lifeCycleConfig = config.lifecycle; + const lifecycleSteps = Object.keys(lifeCycleConfig).map(config => { + return lifeCycleConfig[config]; + }); + this.setState({ + current: lifeCycleConfig[this.props.currentStatus].step, + lifecycleSteps, + }); + } + componentDidUpdate(prevProps, prevState, snapshot) { if ( prevProps.currentStatus !== this.props.currentStatus || @@ -87,12 +103,9 @@ class LifeCycle extends React.Component { this.setState({ reasonText: value }); }; - handleSelectChange = value => { - this.setState({ selectedStatus: value }); - }; - - showReasonModal = () => { + showReasonModal = lifecycleState => { this.setState({ + selectedStatus: lifecycleState, isReasonModalVisible: true, }); }; @@ -105,6 +118,7 @@ class LifeCycle extends React.Component { addLifeCycle = () => { const config = this.props.context; + const lifeCycleConfig = config.lifecycle; const { selectedStatus, reasonText } = this.state; const { uuid } = this.props; const data = { @@ -128,6 +142,7 @@ class LifeCycle extends React.Component { .then(res => { if (res.status === 201) { this.setState({ + current: lifeCycleConfig[selectedStatus].step, isReasonModalVisible: false, isConfirmButtonLoading: false, currentStatus: selectedStatus, @@ -149,14 +164,18 @@ class LifeCycle extends React.Component { }); }; + onChange = current => { + this.setState({ current }); + }; + render() { const { currentStatus, selectedStatus, - isConfirmButtonLoading, + current, + lifecycleSteps, } = this.state; const { lifecycle } = this.props; - const selectedValue = selectedStatus == null ? [] : selectedStatus; let proceedingStates = []; if ( @@ -176,43 +195,47 @@ class LifeCycle extends React.Component { application. Have a thorough review and approval process before directly publishing it to your app store. You can easily transition from one state to another.
- Note: ‘Change State To’ displays only the next states allowed from the - current state - {lifecycle !== null && } - - Current State: {' '} - {currentStatus} -
-
- Change State to: - - + +
+ + {lifecycleSteps.map((step, index) => ( + } + title={step.title} + disabled={current !== step.step} + description={ + current === step.step ? ( +
+

{step.text}

+ {proceedingStates.map(lifecycleState => { + return ( + + ); + })} +
+ ) : ( + '' + ) + } + /> + ))} +
+
{selectedStatus}
-
+ {lifecycle && + selectedStatus && + lifecycle[selectedStatus].isEndState ? ( + + ) : ( +
+ )} + Reason