Fix code issues in App Upload form in APPM UI

feature/appm-store/pbac
Jayasanka 5 years ago
parent 13bdeee883
commit b4d76b893d

@ -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",

@ -34,6 +34,7 @@ import {
Select
} from 'antd';
import axios from "axios";
import "@babel/polyfill";
import {withConfigContext} from "../../../../context/ConfigContext";
const {TextArea} = Input;

@ -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 = (
<div>
<Icon type="plus"/>
@ -395,274 +262,264 @@ class EditReleaseModal extends React.Component {
return (
<div>
<Tooltip title={isAppUpdatable ? "Edit this release" : "This release isn't in an editable state"}>
<Button
disabled={!isAppUpdatable}
size="small" type="primary" onClick={this.showModal}>
<Icon type="edit"/> Edit
</Button>
</Tooltip>
<Modal
title="Edit release"
visible={this.state.visible}
footer={null}
width={580}
onCancel={this.handleCancel}>
<div>
<Spin tip="Uploading..." spinning={loading}>
<Form labelAlign="left" layout="horizontal"
hideRequiredMark
onSubmit={this.handleSubmit}>
{formConfig.specificElements.hasOwnProperty("binaryFile") && (
<Form.Item {...formItemLayout} label="Application">
{getFieldDecorator('binaryFile', {
valuePropName: 'binaryFile',
getValueFromEvent: this.normFile,
required: true,
message: 'Please select application'
})(
<Upload
name="binaryFile"
onChange={this.handleBinaryFileChange}
beforeUpload={() => false}
>
{binaryFiles.length !== 1 && (
<Button>
<Icon type="upload"/> Change
</Button>
)}
</Upload>,
)}
</Form.Item>
)}
{formConfig.specificElements.hasOwnProperty("url") && (
<Form.Item {...formItemLayout} label="URL">
{getFieldDecorator('url', {
rules: [{
required: true,
message: 'Please input the url'
}],
})(
<Input placeholder="url"/>
)}
</Form.Item>
)}
{formConfig.specificElements.hasOwnProperty("version") && (
<Form.Item {...formItemLayout} label="Version">
{getFieldDecorator('version', {
rules: [{
required: true,
message: 'Please input the version'
}],
})(
<Input placeholder="Version"/>
)}
</Form.Item>
)}
<Form.Item {...formItemLayout} label="Icon">
{getFieldDecorator('icon', {
valuePropName: 'icon',
<Row>
<Col md={5}>
</Col>
<Col md={14}>
<Form
labelAlign="right"
layout="horizontal"
onSubmit={this.handleSubmit}>
{formConfig.specificElements.hasOwnProperty("binaryFile") && (
<Form.Item {...formItemLayout}
label="Application"
validateStatus="error"
help={binaryFileHelperText}>
{getFieldDecorator('binaryFile', {
valuePropName: 'binaryFile',
getValueFromEvent: this.normFile,
required: true,
message: 'Please select a icon'
message: 'Please select application'
})(
<Upload
name="logo"
listType="picture-card"
onChange={this.handleIconChange}
beforeUpload={() => false}
onPreview={this.handlePreview}>
{icons.length === 1 ? null : uploadButton}
name="binaryFile"
onChange={this.handleBinaryFileChange}
beforeUpload={() => false}>
{binaryFiles.length !== 1 && (
<Button>
<Icon type="upload"/> Click to upload
</Button>
)}
</Upload>,
)}
</Form.Item>
)}
<Form.Item {...formItemLayout}
label="Icon"
validateStatus="error"
help={iconHelperText}>
{getFieldDecorator('icon', {
valuePropName: 'icon',
getValueFromEvent: this.normFile,
required: true,
message: 'Please select a icon'
})(
<Upload
name="logo"
listType="picture-card"
onChange={this.handleIconChange}
beforeUpload={() => false}
onPreview={this.handlePreview}>
{icons.length === 1 ? null : uploadButton}
</Upload>,
)}
</Form.Item>
<Form.Item {...formItemLayout}
label="Screenshots"
validateStatus="error"
help={screenshotHelperText}>
{getFieldDecorator('screenshots', {
valuePropName: 'icon',
getValueFromEvent: this.normFile,
required: true,
message: 'Please select a icon'
})(
<Upload
name="screenshots"
listType="picture-card"
onChange={this.handleScreenshotChange}
beforeUpload={() => false}
onPreview={this.handlePreview}>
{screenshots.length >= 3 ? null : uploadButton}
</Upload>,
)}
</Form.Item>
<Form.Item {...formItemLayout} label="Screenshots">
{getFieldDecorator('screenshots', {
valuePropName: 'icon',
getValueFromEvent: this.normFile,
required: true,
message: 'Please select a icon'
{formConfig.specificElements.hasOwnProperty("packageName") && (
<Form.Item {...formItemLayout} label="Package Name">
{getFieldDecorator('packageName', {
rules: [{
required: true,
message: 'Please input the package name'
}],
})(
<Upload
name="screenshots"
listType="picture-card"
onChange={this.handleScreenshotChange}
beforeUpload={() => false}
onPreview={this.handlePreview}>
{screenshots.length >= 3 ? null : uploadButton}
</Upload>,
<Input placeholder="Package Name"/>
)}
</Form.Item>
)}
<Form.Item {...formItemLayout} label="Release Type">
{getFieldDecorator('releaseType', {
{formConfig.specificElements.hasOwnProperty("url") && (
<Form.Item {...formItemLayout} label="URL">
{getFieldDecorator('url', {
rules: [{
required: true,
message: 'Please input the Release Type'
message: 'Please input the url'
}],
})(
<Input placeholder="Release Type"/>
<Input placeholder="url"/>
)}
</Form.Item>
)}
<Form.Item {...formItemLayout} label="Description">
{getFieldDecorator('releaseDescription', {
{formConfig.specificElements.hasOwnProperty("version") && (
<Form.Item {...formItemLayout} label="Version">
{getFieldDecorator('version', {
rules: [{
required: true,
message: 'Please enter a description for release'
message: 'Please input the version'
}],
})(
<TextArea placeholder="Enter a description for release"
rows={5}/>
<Input placeholder="Version"/>
)}
</Form.Item>
{(config.deviceTypes.mobileTypes.includes(deviceType)) && (
<Form.Item {...formItemLayout} label="Supported OS Versions">
{getFieldDecorator('supportedOS')(
<div>
<InputGroup>
<Row gutter={8}>
<Col span={11}>
<Form.Item>
{getFieldDecorator('lowerOsVersion', {
rules: [{
required: true,
message: 'Please select Value'
}],
})(
<Select
placeholder="Lower version"
style={{width: "100%"}}
onChange={this.handleLowerOsVersionChange}>
{supportedOsVersions.map(version => (
<Option key={version.versionName}
value={version.versionName}>
{version.versionName}
</Option>
))}
</Select>
)}
</Form.Item>
</Col>
<Col span={2}>
<p> - </p>
</Col>
<Col span={11}>
<Form.Item>
{getFieldDecorator('upperOsVersion', {
rules: [{
required: true,
message: 'Please select Value'
}],
})(
<Select style={{width: "100%"}}
placeholder="Upper version"
onChange={this.handleUpperOsVersionChange}>
{supportedOsVersions.map(version => (
<Option key={version.versionName}
value={version.versionName}>
{version.versionName}
</Option>
))}
</Select>
)}
</Form.Item>
</Col>
</Row>
</InputGroup>
</div>
)}
</Form.Item>
)}
<Form.Item {...formItemLayout} label="Release Type">
{getFieldDecorator('releaseType', {
rules: [{
required: true,
message: 'Please input the Release Type'
}],
})(
<Input placeholder="Release Type"/>
)}
</Form.Item>
<Form.Item {...formItemLayout} label="Description">
{getFieldDecorator('releaseDescription', {
rules: [{
required: true,
message: 'Please enter a description for release'
}],
})(
<TextArea placeholder="Enter a description for release" rows={5}/>
)}
<Form.Item {...formItemLayout} label="Meta Data">
{getFieldDecorator('meta', {
</Form.Item>
{(formConfig.installationType !== "WEB_CLIP" && formConfig.installationType !== "CUSTOM") && (
<Form.Item
{...formItemLayout}
label="Supported OS Versions"
validateStatus={osVersionsValidateStatus}
help={osVersionsHelperText}>
{getFieldDecorator('supportedOS', {
rules: [{
required: true,
message: 'Please fill empty fields'
required: true
}],
initialValue: false
})(
<div>
{
metaData.map((data, index) => {
return (
<InputGroup key={index}>
<Row gutter={8}>
<Col span={10}>
<Input
placeholder="key"
value={data.key}
onChange={(e) => {
metaData[index]['key'] = e.currentTarget.value;
this.setState({
metaData
})
}}/>
</Col>
<Col span={10}>
<Input
placeholder="value"
value={data.value}
onChange={(e) => {
metaData[index].value = e.currentTarget.value;
<InputGroup>
<Row gutter={8}>
<Col span={11}>
<Select
placeholder="Lower version"
style={{width: "100%"}}
onChange={this.handleLowerOsVersionChange}>
{supportedOsVersions.map(version => (
<Option key={version.versionName}
value={version.versionName}>
{version.versionName}
</Option>
))}
</Select>
</Col>
<Col span={2}>
<p> - </p>
</Col>
<Col span={11}>
<Select style={{width: "100%"}}
placeholder="Upper version"
onChange={this.handleUpperOsVersionChange}>
{supportedOsVersions.map(version => (
<Option key={version.versionName}
value={version.versionName}>
{version.versionName}
</Option>
))}
</Select>
</Col>
</Row>
</InputGroup>
</div>
)}
</Form.Item>
)}
<Form.Item {...formItemLayout} label="Meta Data">
{getFieldDecorator('meta', {})(
<div>
{
metaData.map((data, index) => {
return (
<InputGroup key={index}>
<Row gutter={8}>
<Col span={5}>
<Input
placeholder="key"
value={data.key}
onChange={(e) => {
metaData[index]['key'] = e.currentTarget.value;
this.setState({
metaData
})
}}/>
</Col>
<Col span={8}>
<Input
placeholder="value"
value={data.value}
onChange={(e) => {
metaData[index].value = e.currentTarget.value;
this.setState({
metaData
});
}}/>
</Col>
<Col span={3}>
<Button type="dashed"
shape="circle"
icon="minus"
onClick={() => {
metaData.splice(index, 1);
this.setState({
metaData
});
}}/>
</Col>
<Col span={3}>
<Button type="dashed"
shape="circle"
icon="minus"
onClick={() => {
metaData.splice(index, 1);
this.setState({
metaData
});
}}/>
</Col>
</Row>
</InputGroup>
)
}
)
}
<Button type="dashed" icon="plus" onClick={this.addNewMetaData}>
Add
</Button>
</div>
)}
</Form.Item>
<Divider/>
<Form.Item style={{float: "right", marginLeft: 8}}>
<Button type="primary" htmlType="submit">
Update
</Button>
</Form.Item>
<Form.Item style={{float: "right"}}>
<Button htmlType="button" onClick={this.handleCancel}>
Back
</Button>
</Form.Item>
<br/>
</Form>
</Spin>
</div>
<Modal visible={previewVisible} footer={null} onCancel={this.handlePreviewCancel}>
<img alt="Preview Image" style={{width: '100%'}} src={previewImage}/>
</Modal>
</Col>
</Row>
</InputGroup>
)
}
)
}
<Button type="dashed" icon="plus" onClick={this.addNewMetaData}>
Add
</Button>
</div>
)}
</Form.Item>
<Form.Item style={{float: "right", marginLeft: 8}}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
<Form.Item style={{float: "right"}}>
<Button htmlType="button" onClick={this.props.onClickBackButton}>
Back
</Button>
</Form.Item>
</Form>
</Col>
</Row>
<Modal visible={previewVisible} footer={null} onCancel={this.handlePreviewCancel}>
<img alt="Preview Image" style={{width: '100%'}} src={previewImage}/>
</Modal>
</div>
);
}
}
const EditRelease = withConfigContext(Form.create({name: 'add-new-release'})(EditReleaseModal));
export default EditRelease;
export default (Form.create({name: 'app-upload-form'})(NewAppUploadForm));
Loading…
Cancel
Save