From dfc4ce98cb41ebbc811a051bf14656e9b60a90ff Mon Sep 17 00:00:00 2001 From: Jayasanka Date: Sat, 19 Oct 2019 04:57:16 +0530 Subject: [PATCH 1/6] Add improvements to add & edit application forms in APPM UI - Remove price field and tenancy sharing switch - Make supported OS versions a required field --- .../src/components/apps/list-apps/ListApps.js | 6 +- .../apps/release/edit-release/EditRelease.js | 44 +- .../new-app/subForms/NewAppUploadForm.js | 893 ++++++++++-------- 3 files changed, 507 insertions(+), 436 deletions(-) diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/ListApps.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/ListApps.js index 2c7b4f5e258..401b35b79da 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/ListApps.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/ListApps.js @@ -57,10 +57,10 @@ class ListApps extends React.Component { return ( - + - + Apps @@ -82,4 +82,4 @@ class ListApps extends React.Component { } } -export default ListApps; \ No newline at end of file +export default ListApps; 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 4b1c5f97cf0..3cf81bf2b38 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 @@ -59,7 +59,7 @@ function getBase64(file) { } class EditReleaseModal extends React.Component { - + // To add subscription type & tenancy sharing, refer https://gitlab.com/entgra/carbon-device-mgt/merge_requests/331 constructor(props) { super(props); this.state = { @@ -162,12 +162,6 @@ class EditReleaseModal extends React.Component { }, releaseDescription: { value: release.description - }, - price: { - value: release.price - }, - isSharedWithAllTenants: { - value: release.isSharedWithAllTenants } }); @@ -252,7 +246,7 @@ class EditReleaseModal extends React.Component { this.setState({ loading: true }); - const {price, isSharedWithAllTenants, releaseDescription, releaseType} = values; + const {releaseDescription, releaseType} = values; const {icons, screenshots, binaryFiles} = this.state; @@ -261,8 +255,8 @@ class EditReleaseModal extends React.Component { //add release data const release = { description: releaseDescription, - price: (price === undefined) ? 0 : parseInt(price), - isSharedWithAllTenants, + price: 0, + isSharedWithAllTenants: false, metaData: JSON.stringify(this.state.metaData), releaseType: releaseType, }; @@ -282,10 +276,6 @@ class EditReleaseModal extends React.Component { if (specificElements.hasOwnProperty("url")) { release.url = values.url; } - // - // if (specificElements.hasOwnProperty("packageName")) { - // release.packageName = values.packageName; - // } if (icons.length === 1) { data.append('icon', icons[0].originFileObj); @@ -589,30 +579,6 @@ class EditReleaseModal extends React.Component { )} )} - - {getFieldDecorator('price', { - rules: [{ - required: false - }], - })( - - )} - - - - {getFieldDecorator('isSharedWithAllTenants', { - rules: [{ - required: true, - message: 'Please select' - }], - initialValue: false - })( - } - unCheckedChildren={} - /> - )} - - {getFieldDecorator('meta', { rules: [{ @@ -699,4 +665,4 @@ class EditReleaseModal extends React.Component { const EditRelease = withConfigContext(Form.create({name: 'add-new-release'})(EditReleaseModal)); -export default EditRelease; \ No newline at end of file +export default EditRelease; diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/new-app/subForms/NewAppUploadForm.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/new-app/subForms/NewAppUploadForm.js index 79fd42a5f5c..3cf81bf2b38 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/new-app/subForms/NewAppUploadForm.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/new-app/subForms/NewAppUploadForm.js @@ -17,24 +17,37 @@ */ import React from "react"; -import {Button, Col, Form, Icon, Input, Row, Select, Switch, Upload, InputNumber, Modal} from "antd"; -import "@babel/polyfill"; +import { + Modal, + Button, + Icon, + notification, + Spin, + Tooltip, + Upload, + Input, + Switch, + Form, + Divider, + Row, + Col, + Select +} from 'antd'; import axios from "axios"; -import {handleApiError} from "../../../js/Utils"; +import {withConfigContext} from "../../../../context/ConfigContext"; + +const {TextArea} = Input; +const InputGroup = Input.Group; +const {Option} = Select; const formItemLayout = { labelCol: { - xs: {span: 24}, - sm: {span: 8}, + span: 8, }, wrapperCol: { - xs: {span: 24}, - sm: {span: 16}, + span: 16, }, }; -const {Option} = Select; -const {TextArea} = Input; -const InputGroup = Input.Group; function getBase64(file) { return new Promise((resolve, reject) => { @@ -45,30 +58,168 @@ function getBase64(file) { }); } -class NewAppUploadForm extends React.Component { - +class EditReleaseModal extends React.Component { + // To add subscription type & tenancy sharing, refer https://gitlab.com/entgra/carbon-device-mgt/merge_requests/331 constructor(props) { super(props); this.state = { + visible: false, + current: 0, + categories: [], + tags: [], icons: [], screenshots: [], loading: false, binaryFiles: [], - application: null, - isFree: true, - previewVisible: false, - previewImage: '', - binaryFileHelperText: '', - iconHelperText: '', - screenshotHelperText: '', - osVersionsHelperText: '', - osVersionsValidateStatus: 'validating', - metaData: [] + metaData: [], + formConfig: { + specificElements: {} + } }; this.lowerOsVersion = null; this.upperOsVersion = null; } + componentDidMount = () => { + this.generateConfig(); + }; + + generateConfig = () => { + const {type} = this.props; + const formConfig = { + type + }; + + switch (type) { + case "ENTERPRISE": + formConfig.endpoint = "/ent-app-release"; + formConfig.specificElements = { + binaryFile: { + required: true + } + }; + break; + case "PUBLIC": + formConfig.endpoint = "/public-app-release"; + formConfig.specificElements = { + packageName: { + required: true + }, + version: { + required: true + } + }; + break; + case "WEB_CLIP": + formConfig.endpoint = "/web-app-release"; + formConfig.specificElements = { + version: { + required: true + }, + url: { + required: true + } + }; + break; + case "CUSTOM": + formConfig.endpoint = "/custom-app-release"; + formConfig.specificElements = { + binaryFile: { + required: true + }, + packageName: { + required: true + }, + version: { + required: true + } + }; + break; + } + + this.setState({ + formConfig + }); + }; + + + showModal = () => { + const config = this.props.context; + const {app, release} = this.props; + const {formConfig} = this.state; + const {specificElements} = formConfig; + let metaData = []; + + try { + metaData = JSON.parse(release.metaData); + } catch (e) { + + } + + this.props.form.setFields({ + releaseType: { + value: release.releaseType + }, + releaseDescription: { + value: release.description + } + }); + + if ((config.deviceTypes.mobileTypes.includes(this.props.deviceType))) { + const osVersions = release.supportedOsVersions.split("-"); + this.lowerOsVersion = osVersions[0]; + this.upperOsVersion = osVersions[1]; + this.props.form.setFields({ + lowerOsVersion: { + value: osVersions[0] + }, + upperOsVersion: { + value: osVersions[1] + } + }); + } + 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, + metaData + }); + }; + + handleOk = e => { + this.setState({ + visible: false, + }); + }; + + handleCancel = e => { + this.setState({ + visible: false, + }); + }; + normFile = e => { if (Array.isArray(e)) { return e; @@ -76,9 +227,18 @@ class NewAppUploadForm extends React.Component { return e && e.fileList; }; + handleIconChange = ({fileList}) => this.setState({icons: fileList}); + handleBinaryFileChange = ({fileList}) => this.setState({binaryFiles: fileList}); + + handleScreenshotChange = ({fileList}) => this.setState({screenshots: fileList}); + + handleSubmit = e => { e.preventDefault(); - const {formConfig} = this.props; + const {uuid} = this.props.release; + const config = this.props.context; + + const {formConfig} = this.state; const {specificElements} = formConfig; this.props.form.validateFields((err, values) => { @@ -86,123 +246,110 @@ class NewAppUploadForm extends React.Component { this.setState({ loading: true }); - const {price, isSharedWithAllTenants, binaryFile, icon, screenshots, releaseDescription, releaseType} = values; + const {releaseDescription, releaseType} = values; + + const {icons, screenshots, binaryFiles} = this.state; + + const data = new FormData(); //add release data const release = { description: releaseDescription, - price: (price === undefined) ? 0 : parseInt(price), - isSharedWithAllTenants, + price: 0, + isSharedWithAllTenants: false, metaData: JSON.stringify(this.state.metaData), - releaseType: releaseType + releaseType: releaseType, }; + if ((config.deviceTypes.mobileTypes.includes(this.props.deviceType))) { + release.supportedOsVersions = `${this.lowerOsVersion}-${this.upperOsVersion}`; + } + + if (specificElements.hasOwnProperty("binaryFile") && binaryFiles.length === 1) { + data.append('binaryFile', binaryFiles[0].originFileObj); + } + if (specificElements.hasOwnProperty("version")) { release.version = values.version; } + if (specificElements.hasOwnProperty("url")) { release.url = values.url; } - if (specificElements.hasOwnProperty("packageName")) { - release.packageName = values.packageName; + + if (icons.length === 1) { + data.append('icon', icons[0].originFileObj); } - const data = new FormData(); - let isFormValid = true; // flag to check if this form is valid + if (screenshots.length > 0) { + data.append('screenshot1', screenshots[0].originFileObj); + } + + if (screenshots.length > 1) { + data.append('screenshot2', screenshots[1].originFileObj); + } + + if (screenshots.length > 2) { + data.append('screenshot3', screenshots[2].originFileObj); + } + + const json = JSON.stringify(release); + const blob = new Blob([json], { + type: 'application/json' + }); + + data.append("applicationRelease", blob); + + const url = window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications" + formConfig.endpoint + "/" + uuid; + + axios.put( + url, + data + ).then(res => { + if (res.status === 200) { + + const updatedRelease = res.data.data; - if (formConfig.installationType !== "WEB_CLIP" && formConfig.installationType !== "CUSTOM") { - if(this.lowerOsVersion==null || this.upperOsVersion==null){ - isFormValid = false; this.setState({ - osVersionsHelperText: 'Please select supported OS versions', - osVersionsValidateStatus: 'error', + loading: false, + visible: false, }); - }else if(this.lowerOsVersion>=this.upperOsVersion){ - isFormValid = false; - this.setState({ - osVersionsHelperText: 'Please select valid range', - osVersionsValidateStatus: 'error', + + notification["success"]({ + message: "Done!", + description: + "Saved!", }); - }else{ - release.supportedOsVersions = `${this.lowerOsVersion}-${this.upperOsVersion}`; + // console.log(updatedRelease); + this.props.updateRelease(updatedRelease); } - } + }).catch((error) => { + if (error.hasOwnProperty("response") && error.response.status === 401) { + window.location.href = window.location.origin + '/publisher/login'; + } else { + notification["error"]({ + message: "Something went wrong!", + description: + "Sorry, we were unable to complete your request.", + }); - if (specificElements.hasOwnProperty("binaryFile") && this.state.binaryFiles.length !== 1) { - isFormValid = false; - this.setState({ - binaryFileHelperText: 'Please select the application' - }); - } - if (this.state.icons.length !== 1) { - isFormValid = false; - this.setState({ - iconHelperText: 'Please select an icon' - }); - } - if (this.state.screenshots.length !== 3) { - isFormValid = false; - this.setState({ - screenshotHelperText: 'Please select 3 screenshots' - }); - } - if (this.state.screenshots.length !== 3) { - isFormValid = false; + } this.setState({ - screenshotHelperText: 'Please select 3 screenshots' + loading: false }); - } - if(isFormValid) { - data.append('icon', icon[0].originFileObj); - data.append('screenshot1', screenshots[0].originFileObj); - data.append('screenshot2', screenshots[1].originFileObj); - data.append('screenshot3', screenshots[2].originFileObj); - if (specificElements.hasOwnProperty("binaryFile")) { - data.append('binaryFile', binaryFile[0].originFileObj); - } - this.props.onSuccessReleaseData({data, release}); - } + }); } }); }; - handleIconChange = ({fileList}) => { - if (fileList.length === 1) { - this.setState({ - iconHelperText: '' - }); - } - this.setState({ - icons: fileList - }); - }; - handleBinaryFileChange = ({fileList}) => { - if (fileList.length === 1) { - this.setState({ - binaryFileHelperText: '' - }); - } - this.setState({binaryFiles: fileList}); - }; - - handleScreenshotChange = ({fileList}) => { - if (fileList.length === 3) { - this.setState({ - screenshotHelperText: '' - }); - } - this.setState({ - screenshots: fileList - }); - }; - - handlePriceTypeChange = (value) => { + addNewMetaData = () => { this.setState({ - isFree: (value === 'free') - }); + metaData: this.state.metaData.concat({'key': '', 'value': ''}) + }) }; handlePreviewCancel = () => this.setState({previewVisible: false}); + handlePreview = async file => { if (!file.url && !file.preview) { file.preview = await getBase64(file.originFileObj); @@ -214,45 +361,31 @@ class NewAppUploadForm extends React.Component { }); }; - addNewMetaData = () => { - this.setState({ - metaData: this.state.metaData.concat({'key': '', 'value': ''}) - }) - }; - handleLowerOsVersionChange = (lowerOsVersion) => { - this.lowerOsVersion = parseFloat(lowerOsVersion); - this.setState({ - osVersionsValidateStatus: 'validating', - osVersionsHelperText: '' - }); + this.lowerOsVersion = lowerOsVersion; }; handleUpperOsVersionChange = (upperOsVersion) => { - this.upperOsVersion = parseFloat(upperOsVersion); - this.setState({ - osVersionsValidateStatus: 'validating', - osVersionsHelperText: '' - }); + this.upperOsVersion = upperOsVersion; }; render() { - const {formConfig, supportedOsVersions} = this.props; - const {getFieldDecorator} = this.props.form; const { + formConfig, icons, screenshots, + loading, binaryFiles, - isFree, + metaData, previewImage, previewVisible, binaryFileHelperText, iconHelperText, - screenshotHelperText, - metaData, - osVersionsHelperText, - osVersionsValidateStatus + screenshotHelperText } = this.state; + const {getFieldDecorator} = this.props.form; + const {isAppUpdatable, supportedOsVersions, deviceType} = this.props; + const config = this.props.context; const uploadButton = (
@@ -262,302 +395,274 @@ class NewAppUploadForm extends React.Component { return (
- - - - - -
- {formConfig.specificElements.hasOwnProperty("binaryFile") && ( - - {getFieldDecorator('binaryFile', { - valuePropName: 'binaryFile', + + + + +
+ + + {formConfig.specificElements.hasOwnProperty("binaryFile") && ( + + {getFieldDecorator('binaryFile', { + valuePropName: 'binaryFile', + getValueFromEvent: this.normFile, + required: true, + message: 'Please select application' + })( + false} + > + {binaryFiles.length !== 1 && ( + + )} + , + )} + + )} + + {formConfig.specificElements.hasOwnProperty("url") && ( + + {getFieldDecorator('url', { + rules: [{ + required: true, + message: 'Please input the url' + }], + })( + + )} + + )} + + {formConfig.specificElements.hasOwnProperty("version") && ( + + {getFieldDecorator('version', { + rules: [{ + required: true, + message: 'Please input the version' + }], + })( + + )} + + )} + + + {getFieldDecorator('icon', { + valuePropName: 'icon', getValueFromEvent: this.normFile, required: true, - message: 'Please select application' + message: 'Please select a icon' })( false}> - {binaryFiles.length !== 1 && ( - - )} + name="logo" + listType="picture-card" + onChange={this.handleIconChange} + beforeUpload={() => false} + onPreview={this.handlePreview}> + {icons.length === 1 ? null : uploadButton} , )} - )} - - - {getFieldDecorator('icon', { - valuePropName: 'icon', - getValueFromEvent: this.normFile, - required: true, - message: 'Please select a icon' - })( - false} - onPreview={this.handlePreview}> - {icons.length === 1 ? null : uploadButton} - , - )} - - - - {getFieldDecorator('screenshots', { - valuePropName: 'icon', - getValueFromEvent: this.normFile, - required: true, - message: 'Please select a icon' - })( - false} - onPreview={this.handlePreview}> - {screenshots.length >= 3 ? null : uploadButton} - , - )} - - {formConfig.specificElements.hasOwnProperty("packageName") && ( - - {getFieldDecorator('packageName', { - rules: [{ - required: true, - message: 'Please input the package name' - }], + + {getFieldDecorator('screenshots', { + valuePropName: 'icon', + getValueFromEvent: this.normFile, + required: true, + message: 'Please select a icon' })( - + false} + onPreview={this.handlePreview}> + {screenshots.length >= 3 ? null : uploadButton} + , )} - )} - {formConfig.specificElements.hasOwnProperty("url") && ( - - {getFieldDecorator('url', { + + {getFieldDecorator('releaseType', { rules: [{ required: true, - message: 'Please input the url' + message: 'Please input the Release Type' }], })( - + )} - )} - {formConfig.specificElements.hasOwnProperty("version") && ( - - {getFieldDecorator('version', { + + {getFieldDecorator('releaseDescription', { rules: [{ required: true, - message: 'Please input the version' + message: 'Please enter a description for release' }], })( - +