From 0f4eaa575cf4a0831194a1ce0d89bdcf1321ee96 Mon Sep 17 00:00:00 2001 From: Jayasanka Date: Tue, 30 Jul 2019 13:15:44 +0530 Subject: [PATCH] Add ui improvements to APPM - Add breadcrumbs - Fix tag spacing - Add price type selection in New Release form - Change edit button disable when release isn't in an editable state - Add autofill functionality to edit release - Add dynamic device types in add new app form --- .../AppDetailsDrawer/AppDetailsDrawer.js | 4 +- .../apps/list-apps/appsTable/AppsTable.js | 4 +- .../components/apps/release/ReleaseView.js | 42 +++-- .../apps/release/edit-release/EditRelease.js | 89 ++++++++--- .../apps/release/lifeCycle/LifeCycle.js | 61 ++----- .../manage/categories/ManageCategories.js | 5 +- .../manage/categories/ManageTags.js | 4 +- .../new-app/subForms/NewAppDetailsForm.js | 97 ++++++++--- .../new-app/subForms/NewAppUploadForm.js | 3 +- .../components/new-release/AddReleaseForm.js | 39 ++++- .../src/pages/dashboard/Dashboard.js | 3 +- .../add-new-app/AddNewEnterpriseApp.js | 27 ++-- .../dashboard/add-new-app/AddNewPublicApp.js | 21 ++- .../dashboard/add-new-app/AddNewWebClip.js | 26 +-- .../src/pages/dashboard/add-new-app/Step1.js | 150 ------------------ .../src/pages/dashboard/add-new-app/Step2.js | 11 -- .../src/pages/dashboard/add-new-app/Step3.js | 11 -- .../add-new-release/AddNewRelease.js | 30 ++-- .../pages/dashboard/apps/release/Release.js | 54 ++++++- .../src/pages/dashboard/manage/Manage.js | 19 ++- .../pages/dashboard/apps/release/Release.js | 31 ++-- 21 files changed, 369 insertions(+), 362 deletions(-) delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/pages/dashboard/add-new-app/Step1.js delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/pages/dashboard/add-new-app/Step2.js delete mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/pages/dashboard/add-new-app/Step3.js diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer/AppDetailsDrawer.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer/AppDetailsDrawer.js index 5b106f67610..0081bae9a1f 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer/AppDetailsDrawer.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer/AppDetailsDrawer.js @@ -464,7 +464,7 @@ class AppDetailsDrawer extends React.Component { dataSource={app.applicationReleases} renderItem={release => ( - + - + )} /> diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/appsTable/AppsTable.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/appsTable/AppsTable.js index 1beeca3f3b6..0320fd2ba98 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/appsTable/AppsTable.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/appsTable/AppsTable.js @@ -53,7 +53,9 @@ const columns = [ {categories.map(category => { return ( - + {category} ); diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/ReleaseView.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/ReleaseView.js index 51d9ed9d56e..e2ca4547f43 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/ReleaseView.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/ReleaseView.js @@ -1,5 +1,5 @@ import React from "react"; -import {Divider, Row, Col, Typography, Button, Drawer, Icon} from "antd"; +import {Divider, Row, Col, Typography, Button, Drawer, Icon, Tooltip} from "antd"; import StarRatings from "react-star-ratings"; import Reviews from "./review/Reviews"; import "../../../App.css"; @@ -14,10 +14,15 @@ class ReleaseView extends React.Component { const config = this.props.context; const app = this.props.app; const release = (app !== null) ? app.applicationReleases[0] : null; - if (release == null) { + const {lifecycle, currentLifecycleStatus} = this.props; + if (release == null || lifecycle == null) { return null; } + const {isAppUpdatable, isAppInstallable} = lifecycle[currentLifecycleStatus]; + + console.log(isAppInstallable, isAppUpdatable); + const platform = app.deviceType; const defaultPlatformIcons = config.defaultPlatformIcons; let icon = defaultPlatformIcons.default.icon; @@ -57,21 +62,30 @@ class ReleaseView extends React.Component { Version : {release.version}
- + +
- + + +
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/edit-release/EditRelease.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/edit-release/EditRelease.js index 79aa5bd433f..b4ffb5515f9 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/edit-release/EditRelease.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/edit-release/EditRelease.js @@ -1,5 +1,5 @@ import React from "react"; -import {Modal, Button, Icon, notification, Spin, Row, Col, Card, Upload, Input, Switch, Form} from 'antd'; +import {Modal, Button, Icon, notification, Spin, Tooltip, Upload, Input, Switch, Form, Divider} from 'antd'; import axios from "axios"; import {withConfigContext} from "../../../../context/ConfigContext"; @@ -83,6 +83,49 @@ class EditReleaseModal extends React.Component { showModal = () => { + const {release} = this.props; + const {formConfig} = this.state; + const {specificElements} = formConfig; + + this.props.form.setFields({ + releaseType: { + value: release.releaseType + }, + releaseDescription: { + value: release.description + }, + price:{ + value: release.price + }, + isSharedWithAllTenants:{ + value: release.isSharedWithAllTenants + } + }); + + if (specificElements.hasOwnProperty("version")) { + this.props.form.setFields({ + version: { + value: release.version + } + }); + } + + if (specificElements.hasOwnProperty("url")) { + this.props.form.setFields({ + url: { + value: release.url + } + }); + } + + if (specificElements.hasOwnProperty("packageName")) { + this.props.form.setFields({ + packageName: { + value: release.packageName + } + }); + } + this.setState({ visible: true, }); @@ -115,7 +158,7 @@ class EditReleaseModal extends React.Component { handleSubmit = e => { e.preventDefault(); - const {uuid} = this.props; + const {uuid} = this.props.release; const config = this.props.context; const {formConfig} = this.state; @@ -162,15 +205,15 @@ class EditReleaseModal extends React.Component { data.append('icon', icons[0].originFileObj); } - if(screenshots.length>0){ + if (screenshots.length > 0) { data.append('screenshot1', screenshots[0].originFileObj); } - if(screenshots.length>1){ + if (screenshots.length > 1) { data.append('screenshot2', screenshots[1].originFileObj); } - if(screenshots.length>2){ + if (screenshots.length > 2) { data.append('screenshot3', screenshots[2].originFileObj); } @@ -181,7 +224,7 @@ class EditReleaseModal extends React.Component { data.append("applicationRelease", blob); - const url = window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications" + formConfig.endpoint + "/" + uuid; + const url = window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications" + formConfig.endpoint + "/" + uuid; axios.put( url, @@ -199,14 +242,12 @@ class EditReleaseModal extends React.Component { "Saved!", }); - const uuid = res.data.data.uuid; - - // this.props.history.push('/publisher/apps/releases/' + uuid); + window.location.reload(); } }).catch((error) => { if (error.hasOwnProperty("response") && error.response.status === 401) { - window.location.href = window.location.origin+ '/publisher/login'; + window.location.href = window.location.origin + '/publisher/login'; } else { notification["error"]({ message: "Something went wrong!", @@ -227,15 +268,21 @@ class EditReleaseModal extends React.Component { render() { const {formConfig, icons, screenshots, loading, binaryFiles} = this.state; const {getFieldDecorator} = this.props.form; + const {isAppUpdatable} = this.props; + return (
- + + +
@@ -340,14 +387,11 @@ class EditReleaseModal extends React.Component { beforeUpload={() => false} multiple > - {screenshots.length < 3 && ( )} - - , )} @@ -399,11 +443,18 @@ class EditReleaseModal extends React.Component { )} - + + + + + +
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/lifeCycle/LifeCycle.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/lifeCycle/LifeCycle.js index 27dae7a1e37..4d30f334800 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/lifeCycle/LifeCycle.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/release/lifeCycle/LifeCycle.js @@ -34,17 +34,12 @@ class LifeCycle extends React.Component { this.state = { currentStatus: props.currentStatus, selectedStatus: null, - lifecycle: [], reasonText: '', isReasonModalVisible: false, isConfirmButtonLoading: false } } - componentDidMount() { - this.fetchData(); - } - componentDidUpdate(prevProps, prevState, snapshot) { if (prevProps.currentStatus !== this.props.currentStatus || prevProps.uuid !== this.props.uuid) { this.setState({ @@ -53,33 +48,6 @@ class LifeCycle extends React.Component { } } - - fetchData = () => { - const config = this.props.context; - axios.get( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/lifecycle-config" - ).then(res => { - if (res.status === 200) { - const lifecycle = res.data.data; - this.setState({ - lifecycle: lifecycle - }) - } - - }).catch(function (error) { - if (error.hasOwnProperty("response") && error.response.status === 401) { - window.location.href = window.location.origin+ '/publisher/login'; - } else { - notification["error"]({ - message: "There was a problem", - duration: 0, - description: - "Error occurred while trying to load lifecycle configuration.", - }); - } - }); - }; - handleChange = (value) => { this.setState({reasonText: value}) }; @@ -114,7 +82,7 @@ class LifeCycle extends React.Component { }); axios.post( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/life-cycle/" + uuid, + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/life-cycle/" + uuid, data ).then(res => { if (res.status === 201) { @@ -135,7 +103,7 @@ class LifeCycle extends React.Component { }).catch((error) => { if (error.hasOwnProperty("response") && error.response.status === 401) { - window.location.href = window.location.origin+ '/publisher/login'; + window.location.href = window.location.origin + '/publisher/login'; } else { notification["error"]({ message: "Error", @@ -153,12 +121,15 @@ class LifeCycle extends React.Component { render() { - const {currentStatus, lifecycle, selectedStatus} = this.state; + const {currentStatus, selectedStatus} = this.state; + const {lifecycle} = this.props; const selectedValue = selectedStatus == null ? [] : selectedStatus; let proceedingStates = []; - if((lifecycle.hasOwnProperty(currentStatus)) && lifecycle[currentStatus].hasOwnProperty("proceedingStates")){ + + if (lifecycle !== null && (lifecycle.hasOwnProperty(currentStatus)) && lifecycle[currentStatus].hasOwnProperty("proceedingStates")) { proceedingStates = lifecycle[currentStatus].proceedingStates; } + return (
Manage Lifecycle @@ -169,7 +140,7 @@ class LifeCycle extends React.Component { 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: @@ -182,14 +153,14 @@ class LifeCycle extends React.Component { showSearch={true} > {proceedingStates.map(lifecycleState => { - return ( - - ) - }) + return ( + + ) + }) }
} -
+
{tagName} @@ -166,6 +167,7 @@ class ManageTags extends React.Component { const {tempElements} = this.state; const tagElem = ( { e.preventDefault(); @@ -429,7 +431,7 @@ class ManageTags extends React.Component {
} -
+
{ const config = this.props.context; axios.get( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/categories" + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/categories" ).then(res => { if (res.status === 200) { let categories = JSON.parse(res.data.data); @@ -79,7 +81,7 @@ class NewAppDetailsForm extends React.Component { }).catch((error) => { if (error.hasOwnProperty("response") && error.response.status === 401) { - window.location.href = window.location.origin+ '/publisher/login'; + window.location.href = window.location.origin + '/publisher/login'; } else { notification["error"]({ message: "There was a problem", @@ -97,7 +99,7 @@ class NewAppDetailsForm extends React.Component { getTags = () => { const config = this.props.context; axios.get( - window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/tags" + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/tags" ).then(res => { if (res.status === 200) { let tags = JSON.parse(res.data.data); @@ -109,7 +111,7 @@ class NewAppDetailsForm extends React.Component { }).catch((error) => { if (error.hasOwnProperty("response") && error.response.status === 401) { - window.location.href = window.location.origin+ '/publisher/login'; + window.location.href = window.location.origin + '/publisher/login'; } else { notification["error"]({ message: "There was a problem", @@ -124,9 +126,39 @@ class NewAppDetailsForm extends React.Component { }); }; + getDeviceTypes = () => { + const config = this.props.context; + axios.get( + window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt + "/device-types" + ).then(res => { + if (res.status === 200) { + const deviceTypes = JSON.parse(res.data.data); + this.setState({ + deviceTypes, + loading: false, + }); + } + + }).catch((error) => { + if (error.hasOwnProperty("response") && error.response.status === 401) { + window.location.href = window.location.origin + '/publisher/login'; + } else { + notification["error"]({ + message: "There was a problem", + duration: 0, + description: + "Error occurred while trying to load device types.", + }); + } + this.setState({ + loading: false + }); + }); + }; + render() { const {formConfig} = this.props; - const {categories, tags} = this.state; + const {categories, tags, deviceTypes} = this.state; const {getFieldDecorator} = this.props.form; return ( @@ -153,9 +185,22 @@ class NewAppDetailsForm extends React.Component { } )( - + { + deviceTypes.map(deviceType => { + return ( + + ) + }) + } )} @@ -237,19 +282,19 @@ class NewAppDetailsForm extends React.Component { {/* //todo implement add meta data */} {/**/} - {/**/} - {/**/} - {/**/} - {/**/} - {/**/} - {/**/} - {/**/} - {/**/} - {/**/} - {/*