Add UI improvements to edit release view in APPM UI

The following changes are with this commit.
- Add previews of selected images to upload
- Add supported OS versions field
feature/appm-store/pbac
Jayasanka Weerasinghe 5 years ago committed by Saad Sahibjan
parent ac0d01e1d5
commit f710c5489a

@ -28,6 +28,13 @@ import {withConfigContext} from "../../../context/ConfigContext";
const {Title, Text, Paragraph} = Typography;
class ReleaseView extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
render() {
const {app, release} = this.props;
const config = this.props.context;
@ -88,8 +95,10 @@ class ReleaseView extends React.Component {
<EditRelease
isAppUpdatable={isAppUpdatable}
type={app.type}
deviceType={app.deviceType}
release={release}
updateRelease={this.props.updateRelease}
supportedOsVersions={[...this.props.supportedOsVersions]}
/>
</Col>

@ -17,12 +17,28 @@
*/
import React from "react";
import {Modal, Button, Icon, notification, Spin, Tooltip, Upload, Input, Switch, Form, Divider, Row, Col} from 'antd';
import {
Modal,
Button,
Icon,
notification,
Spin,
Tooltip,
Upload,
Input,
Switch,
Form,
Divider,
Row,
Col,
Select
} from 'antd';
import axios from "axios";
import {withConfigContext} from "../../../../context/ConfigContext";
const {TextArea} = Input;
const InputGroup = Input.Group;
const {Option} = Select;
const formItemLayout = {
labelCol: {
@ -33,6 +49,15 @@ const formItemLayout = {
},
};
function getBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
}
class EditReleaseModal extends React.Component {
constructor(props) {
@ -51,6 +76,8 @@ class EditReleaseModal extends React.Component {
specificElements: {}
}
};
this.lowerOsVersion = null;
this.upperOsVersion = null;
}
componentDidMount = () => {
@ -117,15 +144,16 @@ class EditReleaseModal extends React.Component {
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) {
try {
metaData = JSON.parse(release.metaData);
} catch (e) {
}
this.props.form.setFields({
@ -143,14 +171,19 @@ class EditReleaseModal extends React.Component {
}
});
// if (specificElements.hasOwnProperty("packageName")) {
// this.props.form.setFields({
// packageName: {
// value: app.packageName
// }
// });
// }
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: {
@ -232,9 +265,12 @@ class EditReleaseModal extends React.Component {
isSharedWithAllTenants,
metaData: JSON.stringify(this.state.metaData),
releaseType: releaseType,
supportedOsVersions: "4-30"
};
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);
}
@ -322,10 +358,50 @@ class EditReleaseModal extends React.Component {
})
};
handlePreviewCancel = () => this.setState({previewVisible: false});
handlePreview = async file => {
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj);
}
this.setState({
previewImage: file.url || file.preview,
previewVisible: true,
});
};
handleLowerOsVersionChange = (lowerOsVersion) => {
this.lowerOsVersion = lowerOsVersion;
};
handleUpperOsVersionChange = (upperOsVersion) => {
this.upperOsVersion = upperOsVersion;
};
render() {
const {formConfig, icons, screenshots, loading, binaryFiles, metaData} = this.state;
const {
formConfig,
icons,
screenshots,
loading,
binaryFiles,
metaData,
previewImage,
previewVisible,
binaryFileHelperText,
iconHelperText,
screenshotHelperText
} = this.state;
const {getFieldDecorator} = this.props.form;
const {isAppUpdatable} = this.props;
const {isAppUpdatable, supportedOsVersions, deviceType} = this.props;
const config = this.props.context;
const uploadButton = (
<div>
<Icon type="plus"/>
<div className="ant-upload-text">Select</div>
</div>
);
return (
<div>
@ -340,8 +416,8 @@ class EditReleaseModal extends React.Component {
title="Edit release"
visible={this.state.visible}
footer={null}
onCancel={this.handleCancel}
>
width={580}
onCancel={this.handleCancel}>
<div>
<Spin tip="Uploading..." spinning={loading}>
<Form labelAlign="left" layout="horizontal"
@ -370,19 +446,6 @@ class EditReleaseModal extends React.Component {
</Form.Item>
)}
{/*{formConfig.specificElements.hasOwnProperty("packageName") && (*/}
{/* <Form.Item {...formItemLayout} label="Package Name">*/}
{/* {getFieldDecorator('packageName', {*/}
{/* rules: [{*/}
{/* required: true,*/}
{/* message: 'Please input the package name'*/}
{/* }],*/}
{/* })(*/}
{/* <Input placeholder="Package Name"/>*/}
{/* )}*/}
{/* </Form.Item>*/}
{/*)}*/}
{formConfig.specificElements.hasOwnProperty("url") && (
<Form.Item {...formItemLayout} label="URL">
{getFieldDecorator('url', {
@ -418,19 +481,15 @@ class EditReleaseModal extends React.Component {
})(
<Upload
name="logo"
listType="picture-card"
onChange={this.handleIconChange}
beforeUpload={() => false}
>
{icons.length !== 1 && (
<Button>
<Icon type="upload"/> Change
</Button>
)}
onPreview={this.handlePreview}>
{icons.length === 1 ? null : uploadButton}
</Upload>,
)}
</Form.Item>
<Form.Item {...formItemLayout} label="Screenshots">
{getFieldDecorator('screenshots', {
valuePropName: 'icon',
@ -440,15 +499,11 @@ class EditReleaseModal extends React.Component {
})(
<Upload
name="screenshots"
listType="picture-card"
onChange={this.handleScreenshotChange}
beforeUpload={() => false}
multiple
>
{screenshots.length < 3 && (
<Button>
<Icon type="upload"/> Click to upload
</Button>
)}
onPreview={this.handlePreview}>
{screenshots.length >= 3 ? null : uploadButton}
</Upload>,
)}
</Form.Item>
@ -475,7 +530,65 @@ class EditReleaseModal extends React.Component {
rows={5}/>
)}
</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="Price">
{getFieldDecorator('price', {
rules: [{
@ -575,6 +688,9 @@ class EditReleaseModal extends React.Component {
</Form>
</Spin>
</div>
<Modal visible={previewVisible} footer={null} onCancel={this.handlePreviewCancel}>
<img alt="Preview Image" style={{width: '100%'}} src={previewImage}/>
</Modal>
</Modal>
</div>
);

@ -37,7 +37,6 @@ class LifeCycleDetailsModal extends React.Component {
};
handleCancel = e => {
console.log(e);
this.setState({
visible: false,
});

@ -39,7 +39,6 @@ class AddNewPage extends React.Component {
handleCancel = e => {
console.log(e);
this.setState({
visible: false,
});

@ -37,14 +37,12 @@ class GooglePlayIframe extends React.Component {
};
handleOk = e => {
console.log(e);
this.setState({
visible: false,
});
};
handleCancel = e => {
console.log(e);
this.setState({
visible: false,
});

@ -43,14 +43,12 @@ class ManagedConfigurationsIframe extends React.Component {
};
handleOk = e => {
console.log(e);
this.setState({
visible: false,
});
};
handleCancel = e => {
console.log(e);
this.setState({
visible: false,
});
@ -116,7 +114,6 @@ class ManagedConfigurationsIframe extends React.Component {
updateConfig = (method, event) => {
const {packageName} = this.props;
this.setState({loading: true});
console.log(event);
const data = {
mcmId: event.mcmId,
@ -151,7 +148,6 @@ class ManagedConfigurationsIframe extends React.Component {
deleteConfig = (event) => {
const {packageName} = this.props;
this.setState({loading: true});
console.log(event);
//send request to the invoker
axios.delete(

@ -47,7 +47,6 @@ class Pages extends React.Component {
rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
// console.lohhhg(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
this.setState({
selectedRows: selectedRows
})

@ -84,9 +84,6 @@ class NewAppUploadForm extends React.Component {
this.setState({
loading: true
});
console.log(values);
const {price, isSharedWithAllTenants, binaryFile, icon, screenshots, releaseDescription, releaseType} = values;
//add release data
@ -234,8 +231,7 @@ class NewAppUploadForm extends React.Component {
<Form
labelAlign="right"
layout="horizontal"
onSubmit={this.handleSubmit}
>
onSubmit={this.handleSubmit}>
{formConfig.specificElements.hasOwnProperty("binaryFile") && (
<Form.Item {...formItemLayout}
label="Application"
@ -250,8 +246,7 @@ class NewAppUploadForm extends React.Component {
<Upload
name="binaryFile"
onChange={this.handleBinaryFileChange}
beforeUpload={() => false}
>
beforeUpload={() => false}>
{binaryFiles.length !== 1 && (
<Button>
<Icon type="upload"/> Click to upload
@ -277,8 +272,7 @@ class NewAppUploadForm extends React.Component {
listType="picture-card"
onChange={this.handleIconChange}
beforeUpload={() => false}
onPreview={this.handlePreview}
>
onPreview={this.handlePreview}>
{icons.length === 1 ? null : uploadButton}
</Upload>,
)}
@ -418,7 +412,6 @@ class NewAppUploadForm extends React.Component {
</Select>,
)}
</Form.Item>
<Form.Item {...formItemLayout} label="Price">
{getFieldDecorator('price', {
rules: [{
@ -437,7 +430,6 @@ class NewAppUploadForm extends React.Component {
/>
)}
</Form.Item>
<Form.Item {...formItemLayout} label="Is Shared?">
{getFieldDecorator('isSharedWithAllTenants', {
rules: [{
@ -450,7 +442,6 @@ class NewAppUploadForm extends React.Component {
unCheckedChildren={<Icon type="close"/>}
/>
)}
</Form.Item>
<Form.Item {...formItemLayout} label="Meta Data">
{getFieldDecorator('meta', {
@ -510,7 +501,6 @@ class NewAppUploadForm extends React.Component {
</Button>
</div>
)}
</Form.Item>
<Form.Item style={{float: "right", marginLeft: 8}}>
<Button type="primary" htmlType="submit">
@ -531,7 +521,6 @@ class NewAppUploadForm extends React.Component {
</div>
);
}
}
export default (Form.create({name: 'app-upload-form'})(NewAppUploadForm));

@ -39,7 +39,8 @@ class Release extends React.Component {
uuid: null,
release: null,
currentLifecycleStatus: null,
lifecycle: null
lifecycle: null,
supportedOsVersions:[]
};
}
@ -85,14 +86,17 @@ class Release extends React.Component {
loading: false,
uuid: uuid
});
if(config.deviceTypes.mobileTypes.includes(app.deviceType)){
this.getSupportedOsVersions(app.deviceType);
}else{
this.getLifecycle();
}
}
}).catch((error) => {
handleApiError(error, "Error occurred while trying to load the release.");
this.setState({loading: false});
});
this.getLifecycle();
};
getLifecycle = () => {
@ -112,6 +116,28 @@ class Release extends React.Component {
});
};
getSupportedOsVersions = (deviceType) => {
const config = this.props.context;
axios.get(
window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt +
`/admin/device-types/${deviceType}/versions`
).then(res => {
if (res.status === 200) {
let supportedOsVersions = JSON.parse(res.data.data);
this.setState({
supportedOsVersions,
loading: false,
});
this.getLifecycle();
}
}).catch((error) => {
handleApiError(error, "Error occurred while trying to load supported OS versions.");
this.setState({
loading: false
});
});
};
render() {
const {app, release, currentLifecycleStatus, lifecycle, loading} = this.state;
@ -138,6 +164,7 @@ class Release extends React.Component {
currentLifecycleStatus={currentLifecycleStatus}
lifecycle={lifecycle}
updateRelease={this.updateRelease}
supportedOsVersions = {[...this.state.supportedOsVersions]}
/>)
}
</Skeleton>

@ -62,16 +62,16 @@ class ReleaseView extends React.Component {
headers: {'X-Platform': config.serverConfig.platform}
}
).then(res => {
if (res.status === 200) {
if (res.status === 200 || res.status === 201) {
this.setState({
loading: false,
appInstallModalVisible: false,
appUnInstallModalVisible: false,
appUninstallModalVisible: false,
});
notification["success"]({
message: 'Done!',
description:
'App '+operation+'ed triggered.',
'Operation triggered.',
});
} else {
this.setState({

@ -193,7 +193,7 @@ class DeviceUninstall extends React.Component {
type: device.type
});
});
this.props.onUninstall("devices", payload, "uninstall", null);
this.props.onUninstall("devices", payload, "uninstall", timestamp);
};
render() {

@ -88,7 +88,7 @@ class GroupUninstall extends React.Component {
value.map(val=>{
data.push(val.key);
});
this.props.onUninstall("group", data, "uninstall",null);
this.props.onUninstall("group", data, "uninstall",timestamp);
};
render() {

@ -87,7 +87,7 @@ class RoleUninstall extends React.Component {
value.map(val=>{
data.push(val.key);
});
this.props.onUninstall("role", data, "uninstall",null);
this.props.onUninstall("role", data, "uninstall",timestamp);
};
render() {

@ -86,7 +86,7 @@ class UserUninstall extends React.Component {
value.map(val => {
data.push(val.key);
});
this.props.onUninstall("user", data, "uninstall",null);
this.props.onUninstall("user", data, "uninstall",timestamp);
};
render() {

@ -46,6 +46,14 @@ class InstallModalFooter extends React.Component{
})
};
triggerInstallOperation = () =>{
this.props.operation();
};
triggerScheduledInstallOperation = () =>{
const {scheduledTime} =this.state;
this.props.operation(scheduledTime);
};
render() {
const {scheduledTime,isScheduledInstallVisible} =this.state;
const {disabled, type} = this.props;
@ -56,7 +64,7 @@ class InstallModalFooter extends React.Component{
display: (!isScheduledInstallVisible)?'block':'none'
}}>
<Button style={{margin: 5}} disabled={disabled} htmlType="button" type="primary"
onClick={this.props.operation}>
onClick={this.triggerInstallOperation}>
{type}
</Button>
<Button style={{margin: 5}} disabled={disabled} htmlType="button"
@ -76,9 +84,7 @@ class InstallModalFooter extends React.Component{
style={{margin: 5}}
htmlType="button"
type="primary"
onClick={()=>{
this.props.operation(scheduledTime);
}}>
onClick={this.triggerScheduledInstallOperation}>
Schedule
</Button>
<Button style={{margin: 5}} htmlType="button"

@ -41,7 +41,6 @@ class EditReview extends React.Component {
componentDidMount() {
const {content,rating,id} = this.props.review;
console.log(this.props.review);
this.setState({
content,
rating

@ -19,7 +19,6 @@
import {notification} from "antd";
export const handleApiError = (error, message) => {
console.log(error);
if (error.hasOwnProperty("response") && error.response.status === 401) {
const redirectUrl = encodeURI(window.location.href);
window.location.href = window.location.origin + `/store/login?redirect=${redirectUrl}`;

@ -80,7 +80,6 @@ class NormalLoginForm extends React.Component {
handleSubmit = (e) => {
const thisForm = this;
const config = this.props.context;
console.log(config);
e.preventDefault();
this.props.form.validateFields((err, values) => {

Loading…
Cancel
Save