diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json index 565064db72a..dece5f93636 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json @@ -15,11 +15,15 @@ "acorn": "^6.2.0", "antd": "^3.23.6", "axios": "^0.19.0", + "babel-eslint": "^9.0.0", "d3": "^5.9.7", "dagre": "^0.8.4", + "eslint": "^5.16.0", + "eslint-plugin-import": "^2.18.2", + "eslint-plugin-jsx-a11y": "^6.2.3", + "eslint-plugin-react": "^7.16.0", "fetch": "^1.1.0", - "gapi": "0.0.3", - "gapi-client": "0.0.3", + "imagemin": "^6.1.0", "keymirror": "^0.1.1", "rc-tween-one": "^2.4.1", "react-d3-graph": "^2.1.0", @@ -34,7 +38,8 @@ "react-star-ratings": "^2.3.0", "redux-thunk": "^2.3.0", "shade-blend-color": "^1.0.0", - "storm-react-diagrams": "^5.2.1" + "storm-react-diagrams": "^5.2.1", + "typescript": "^3.6.4" }, "devDependencies": { "@babel/core": "^7.5.0", 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 3cf81bf2b38..062fa565423 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 @@ -34,6 +34,7 @@ import { Select } from 'antd'; import axios from "axios"; +import "@babel/polyfill"; import {withConfigContext} from "../../../../context/ConfigContext"; const {TextArea} = Input; 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 57ca8f1f57d..fe09bc91939 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,37 +17,24 @@ */ import React from "react"; -import { - Modal, - Button, - Icon, - notification, - Spin, - Tooltip, - Upload, - Input, - Switch, - Form, - Divider, - Row, - Col, - Select -} from 'antd'; +import {Button, Col, Form, Icon, Input, Row, Select, Switch, Upload, InputNumber, Modal} from "antd"; +import "@babel/polyfill"; import axios from "axios"; -import {withConfigContext} from "../../../context/ConfigContext"; - -const {TextArea} = Input; -const InputGroup = Input.Group; -const {Option} = Select; +import {handleApiError} from "../../../js/Utils"; const formItemLayout = { labelCol: { - span: 8, + xs: {span: 24}, + sm: {span: 8}, }, wrapperCol: { - span: 16, + xs: {span: 24}, + sm: {span: 16}, }, }; +const {Option} = Select; +const {TextArea} = Input; +const InputGroup = Input.Group; function getBase64(file) { return new Promise((resolve, reject) => { @@ -58,168 +45,30 @@ 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 +class NewAppUploadForm extends React.Component { + constructor(props) { super(props); this.state = { - visible: false, - current: 0, - categories: [], - tags: [], icons: [], screenshots: [], loading: false, binaryFiles: [], - metaData: [], - formConfig: { - specificElements: {} - } + application: null, + isFree: true, + previewVisible: false, + previewImage: '', + binaryFileHelperText: '', + iconHelperText: '', + screenshotHelperText: '', + osVersionsHelperText: '', + osVersionsValidateStatus: 'validating', + metaData: [] }; 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; @@ -227,18 +76,9 @@ class EditReleaseModal 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 {uuid} = this.props.release; - const config = this.props.context; - - const {formConfig} = this.state; + const {formConfig} = this.props; const {specificElements} = formConfig; this.props.form.validateFields((err, values) => { @@ -246,11 +86,7 @@ class EditReleaseModal extends React.Component { this.setState({ loading: true }); - const {releaseDescription, releaseType} = values; - - const {icons, screenshots, binaryFiles} = this.state; - - const data = new FormData(); + const {price, isSharedWithAllTenants, binaryFile, icon, screenshots, releaseDescription, releaseType} = values; //add release data const release = { @@ -258,98 +94,115 @@ class EditReleaseModal extends React.Component { 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 (icons.length === 1) { - data.append('icon', icons[0].originFileObj); - } - - if (screenshots.length > 0) { - data.append('screenshot1', screenshots[0].originFileObj); + if (specificElements.hasOwnProperty("packageName")) { + release.packageName = values.packageName; } - 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; + const data = new FormData(); + let isFormValid = true; // flag to check if this form is valid + if (formConfig.installationType !== "WEB_CLIP" && formConfig.installationType !== "CUSTOM") { + if (this.lowerOsVersion == null || this.upperOsVersion == null) { + isFormValid = false; this.setState({ - loading: false, - visible: false, + osVersionsHelperText: 'Please select supported OS versions', + osVersionsValidateStatus: 'error', }); - - notification["success"]({ - message: "Done!", - description: - "Saved!", + } else if (this.lowerOsVersion >= this.upperOsVersion) { + isFormValid = false; + this.setState({ + osVersionsHelperText: 'Please select valid range', + osVersionsValidateStatus: 'error', }); - // 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.", - }); - + release.supportedOsVersions = `${this.lowerOsVersion}-${this.upperOsVersion}`; } + } + + if (specificElements.hasOwnProperty("binaryFile") && this.state.binaryFiles.length !== 1) { + isFormValid = false; this.setState({ - loading: false + 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' + }); + } + 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}); + } } }); }; - addNewMetaData = () => { + handleIconChange = ({fileList}) => { + if (fileList.length === 1) { + this.setState({ + iconHelperText: '' + }); + } this.setState({ - metaData: this.state.metaData.concat({'key': '', 'value': ''}) - }) + icons: fileList + }); + }; + handleBinaryFileChange = ({fileList}) => { + if (fileList.length === 1) { + this.setState({ + binaryFileHelperText: '' + }); + } + this.setState({binaryFiles: fileList}); }; - handlePreviewCancel = () => this.setState({previewVisible: false}); + handleScreenshotChange = ({fileList}) => { + if (fileList.length === 3) { + this.setState({ + screenshotHelperText: '' + }); + } + this.setState({ + screenshots: fileList + }); + }; + + handlePriceTypeChange = (value) => { + this.setState({ + isFree: (value === 'free') + }); + }; + handlePreviewCancel = () => this.setState({previewVisible: false}); handlePreview = async file => { if (!file.url && !file.preview) { file.preview = await getBase64(file.originFileObj); @@ -361,31 +214,45 @@ class EditReleaseModal extends React.Component { }); }; + addNewMetaData = () => { + this.setState({ + metaData: this.state.metaData.concat({'key': '', 'value': ''}) + }) + }; + handleLowerOsVersionChange = (lowerOsVersion) => { - this.lowerOsVersion = lowerOsVersion; + this.lowerOsVersion = parseFloat(lowerOsVersion); + this.setState({ + osVersionsValidateStatus: 'validating', + osVersionsHelperText: '' + }); }; handleUpperOsVersionChange = (upperOsVersion) => { - this.upperOsVersion = upperOsVersion; + this.upperOsVersion = parseFloat(upperOsVersion); + this.setState({ + osVersionsValidateStatus: 'validating', + osVersionsHelperText: '' + }); }; render() { + const {formConfig, supportedOsVersions} = this.props; + const {getFieldDecorator} = this.props.form; const { - formConfig, icons, screenshots, - loading, binaryFiles, - metaData, + isFree, previewImage, previewVisible, binaryFileHelperText, iconHelperText, - screenshotHelperText + screenshotHelperText, + metaData, + osVersionsHelperText, + osVersionsValidateStatus } = this.state; - const {getFieldDecorator} = this.props.form; - const {isAppUpdatable, supportedOsVersions, deviceType} = this.props; - const config = this.props.context; const uploadButton = (
@@ -395,274 +262,264 @@ class EditReleaseModal extends React.Component { return (
- - - - -
- -
- {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', + + + + + + + {formConfig.specificElements.hasOwnProperty("binaryFile") && ( + + {getFieldDecorator('binaryFile', { + valuePropName: 'binaryFile', getValueFromEvent: this.normFile, required: true, - message: 'Please select a icon' + message: 'Please select application' })( false} - onPreview={this.handlePreview}> - {icons.length === 1 ? null : uploadButton} + name="binaryFile" + onChange={this.handleBinaryFileChange} + beforeUpload={() => false}> + {binaryFiles.length !== 1 && ( + + )} , )} + )} + + + {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} + , + )} + - - {getFieldDecorator('screenshots', { - valuePropName: 'icon', - getValueFromEvent: this.normFile, - required: true, - message: 'Please select a icon' + {formConfig.specificElements.hasOwnProperty("packageName") && ( + + {getFieldDecorator('packageName', { + rules: [{ + required: true, + message: 'Please input the package name' + }], })( - false} - onPreview={this.handlePreview}> - {screenshots.length >= 3 ? null : uploadButton} - , + )} + )} - - {getFieldDecorator('releaseType', { + {formConfig.specificElements.hasOwnProperty("url") && ( + + {getFieldDecorator('url', { rules: [{ required: true, - message: 'Please input the Release Type' + message: 'Please input the url' }], })( - + )} + )} - - {getFieldDecorator('releaseDescription', { + {formConfig.specificElements.hasOwnProperty("version") && ( + + {getFieldDecorator('version', { rules: [{ required: true, - message: 'Please enter a description for release' + message: 'Please input the version' }], })( -