Merge branch 'application-mgt-new' into 'application-mgt-new'

Complete add app functionality in APPM UI

See merge request entgra/carbon-device-mgt!152
4.x.x
Dharmakeerthi Lasantha 6 years ago
commit 79543df6d1

@ -41,7 +41,7 @@ class AppDetailsDrawer extends React.Component {
<br/>
<br/>
<span>
{app.appCategories.map(category => {
{app.categories.map(category => {
return (
<Tag color="blue" key={category} style={{paddingBottom: 5}}>
{category}

@ -28,10 +28,10 @@ const columns = [
},
{
title: 'Categories',
dataIndex: 'appCategories',
render: appCategories => (
dataIndex: 'categories',
render: categories => (
<span>
{appCategories.map(category => {
{categories.map(category => {
return (
<Tag color="blue" key={category}>
{category}
@ -104,17 +104,13 @@ class AppsTable extends React.Component {
params.page = 1;
}
const extraParams = {
const data = {
offset: 10 * (params.page - 1),
limit: 10
};
// note: encode with '%26' not '&'
const encodedExtraParams = Object.keys(extraParams).map(key => key + '=' + extraParams[key]).join('&');
const data = {
};
axios.post(
config.serverConfig.protocol + "://"+config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri +config.serverConfig.invoker.publisher+"/applications?"+encodedExtraParams,
config.serverConfig.protocol + "://"+config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri +config.serverConfig.invoker.publisher+"/applications",
data,
{
headers: { 'X-Platform': config.serverConfig.platform }

@ -1,72 +1,35 @@
import React from "react";
import "antd/dist/antd.css";
import {
PageHeader,
Typography,
Card,
Steps,
Button,
message,
Row,
Col,
Tag,
Tooltip,
Input,
Icon,
Select,
Switch,
Form,
Upload,
Divider, notification
Divider,
notification,
Spin
} from "antd";
import IconImage from "./IconImg";
import UploadScreenshots from "./UploadScreenshots";
import axios from "axios";
import {withRouter} from 'react-router-dom'
import config from "../../../public/conf/config.json";
const Paragraph = Typography;
const Dragger = Upload.Dragger;
const props = {
name: 'file',
multiple: false,
action: '//jsonplaceholder.typicode.com/posts/',
onChange(info) {
const status = info.file.status;
if (status !== 'uploading') {
console.log(info.file, info.fileList);
}
if (status === 'done') {
message.success(`${info.file.name} file uploaded successfully.`);
} else if (status === 'error') {
message.error(`${info.file.name} file upload failed.`);
}
},
};
//
// const steps = [{
// title: 'First',
// content: Step1
// }, {
// title: 'Second',
// content: Step2,
// }, {
// title: 'Last',
// content: Step3,
// }];
const {Option} = Select;
const {TextArea} = Input;
const InputGroup = Input.Group;
const formItemLayout = {
labelCol: {
span: 4,
span: 5,
},
wrapperCol: {
span: 20,
span: 19,
},
};
@ -79,7 +42,9 @@ class AddNewAppFormComponent extends React.Component {
categories: [],
tags: [],
icons: [],
screenshots: []
screenshots: [],
loading: false,
binaryFiles: []
};
}
@ -148,144 +113,119 @@ class AddNewAppFormComponent extends React.Component {
handleSubmit = e => {
e.preventDefault();
const {formConfig} = this.props;
const {specificElements} = formConfig;
this.props.form.validateFields((err, values) => {
if (!err) {
const {name, description, appCategories, tags, deviceType, price, isSharedWithAllTenants, binaryFile, icon, screenshots} = values;
const payload = {
binaryFile: binaryFile[0].originFileObj,
icon: icon[0].originFileObj,
screenshot1: screenshots[0].originFileObj,
screenshot2: screenshots[1].originFileObj,
screenshot3: screenshots[2].originFileObj,
application: {
this.setState({
loading: true
});
const {name, description, categories, tags, price, isSharedWithAllTenants, binaryFile, icon, screenshots, releaseDescription,releaseType} = values;
const application = {
name,
description,
appCategories,
subType: (price === undefined || parseInt(price) === 0) ? "FREE" : "PAID",
categories,
subMethod: (price === undefined || parseInt(price) === 0) ? "FREE" : "PAID",
tags,
unrestrictedRoles: [],
deviceType,
entAppReleaseWrappers: [{
description,
};
const data = new FormData();
if (formConfig.installationType !== "WEB_CLIP") {
application.deviceType = values.deviceType;
}else{
application.type = "WEB_CLIP";
application.deviceType ="ALL";
}
if (specificElements.hasOwnProperty("binaryFile")) {
data.append('binaryFile', binaryFile[0].originFileObj);
}
//add release data
const release = {
description: releaseDescription,
price: (price === undefined) ? 0 : parseInt(price),
isSharedWithAllTenants,
metaData: "string",
supportedOsVersions: "4.0-10.0"
}]
}
releaseType: releaseType
};
console.log(payload);
// let data = new FormData();
//
// const url = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/ent-app";
//
// data.append('binaryFile', binaryFile[0].originFileObj);
// data.append('icon', icon[0].originFileObj);
// data.append('screenshot1', screenshots[0].originFileObj);
// data.append('screenshot2', screenshots[1].originFileObj);
// data.append('screenshot3', screenshots[2].originFileObj);
// data.append('application', JSON.toString(payload.application));
// let request = new XMLHttpRequest();
// request.open('POST', url);
// request.send(data);
// var xhr = new XMLHttpRequest();
// // xhr.withCredentials = true;
//
// xhr.addEventListener("readystatechange", function () {
// if (this.readyState === 4) {
// console.log(this.responseText);
// }
// });
//
// xhr.open("POST", "https://localhost:9443/ui-request-handler/invoke/application-mgt-publisher/v1.0/applications/ent-app");
// xhr.open("GET", "https://localhost:9443/ui-request-handler/invoke/application-mgt-publisher/v1.0/applications/tags");
// xhr.setRequestHeader("Content-Type", "multipart/mixed");
// xhr.setRequestHeader("X-Platform", "publisher");
//
// // xhr.setRequestHeader("Accept", "*/*");
//
// xhr.send(data);
// xhr.send();
// const options = {method: 'POST', body: data};
//
// fetch(url, options).then(function (response) {
// console.log(response);
// });
// axios.post(
// url,
// data,
// {
// headers:{
// 'X-Platform': config.serverConfig.platform,
// 'Content-Type': 'multipart/mixed',
// 'content-type': 'multipart/form-data'
// },
// 'Content-Type': 'multipart/mixed',
// 'content-type': 'multipart/form-data'
// }
// ).then(res => {
// if (res.status === 201) {
// this.setState({
// loading: false,
// });
//
// notification["success"]({
// message: "Done!",
// description:
// "New app was added successfully",
// });
// }
//
// }).catch((error) => {
// if (error.response.status === 401) {
// window.location.href = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + '/publisher/login';
// } else {
// message.warning('Something went wrong');
//
// }
// this.setState({
// loading: false
// });
// });
let data = new FormData();
data.append('binaryFile', binaryFile[0].originFileObj);
if (formConfig.installationType !== "WEB_CLIP") {
release.supportedOsVersions = "4.0-10.0";
}
if (specificElements.hasOwnProperty("version")) {
release.version = values.version;
}
if (specificElements.hasOwnProperty("url")) {
release.url = values.url;
}
if (specificElements.hasOwnProperty("packageName")) {
release.packageName = values.packageName;
}
//add release wrapper
application[formConfig.releaseWrapperName] = [release];
data.append('icon', icon[0].originFileObj);
data.append('screenshot1', screenshots[0].originFileObj);
data.append('screenshot2', screenshots[1].originFileObj);
data.append('screenshot3', screenshots[2].originFileObj);
const json = JSON.stringify(payload.application);
const json = JSON.stringify(application);
const blob = new Blob([json], {
type: 'application/json'
});
data.append('application', blob);
data.append(formConfig.jsonPayloadName, blob);
console.log(application);
const url = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications" + formConfig.endpoint;
axios.post(
url,
data,
{
headers: {
'X-Platform': config.serverConfig.platform
},
}
).then(res => {
if (res.status === 201) {
this.setState({
loading: false,
});
notification["success"]({
message: "Done!",
description:
"New app was added successfully",
});
let xhr = new XMLHttpRequest();
xhr.withCredentials = true;
this.props.history.push('/publisher/apps');
// window.location.href = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + '/publisher/apps';
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
}).catch((error) => {
if (error.response.status === 401) {
window.location.href = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + '/publisher/login';
} else {
notification["error"]({
message: "Something went wrong!",
description:
"Sorry, we were unable to complete your request.",
});
const url = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/ent-app";
xhr.open("POST", url);
xhr.setRequestHeader("X-Platform", "publisher");
xhr.send(data);
}
this.setState({
loading: false
});
});
}
});
};
@ -299,6 +239,7 @@ class AddNewAppFormComponent extends React.Component {
};
handleIconChange = ({fileList}) => this.setState({icons: fileList});
handleBinaryFileChange = ({fileList}) => this.setState({icons: fileList});
handleScreenshotChange = ({fileList}) => this.setState({screenshots: fileList});
@ -311,10 +252,12 @@ class AddNewAppFormComponent extends React.Component {
};
render() {
const {categories, tags, icons, screenshots} = this.state;
const {categories, tags, icons, screenshots, loading, binaryFiles} = this.state;
const {getFieldDecorator} = this.props.form;
const {formConfig} = this.props;
return (
<div>
<Spin tip="Uploading..." spinning={loading}>
<Row>
<Col span={20} offset={2}>
<Card>
@ -324,29 +267,35 @@ class AddNewAppFormComponent extends React.Component {
<Row>
<Col span={12}>
<div>
{/*device type*/}
{formConfig.installationType !== "WEB_CLIP" && (
<Form.Item {...formItemLayout} label="Device Type">
{getFieldDecorator('deviceType', {
rules: [{
required: false,
rules: [
{
required: true,
message: 'Please select device type'
},
{
validator: this.validateIcon
}],
})(
}
],
}
)(
<Select placeholder="select device type">
<Option key="android">Android</Option>
<Option key="ios">iOS</Option>
</Select>
)}
</Form.Item>
)}
{/*app name*/}
<Form.Item {...formItemLayout} label="App Name">
{getFieldDecorator('name', {
rules: [{
required: false,
required: true,
message: 'Please input a name'
}],
})(
@ -358,7 +307,7 @@ class AddNewAppFormComponent extends React.Component {
<Form.Item {...formItemLayout} label="Description">
{getFieldDecorator('description', {
rules: [{
required: false,
required: true,
message: 'Please enter a description'
}],
})(
@ -366,9 +315,9 @@ class AddNewAppFormComponent extends React.Component {
)}
</Form.Item>
<Form.Item {...formItemLayout} label="Categories">
{getFieldDecorator('appCategories', {
{getFieldDecorator('categories', {
rules: [{
required: false,
required: true,
message: 'Please select categories'
}],
})(
@ -391,32 +340,11 @@ class AddNewAppFormComponent extends React.Component {
</Select>
)}
</Form.Item>
<Form.Item {...formItemLayout} label="Price">
{getFieldDecorator('price', {
rules: [{
required: false
}],
})(
<Input prefix="$" placeholder="00.00"/>
)}
</Form.Item>
<Form.Item {...formItemLayout} label="Is Shared?">
{getFieldDecorator('isSharedWithAllTenants', {
rules: [{
required: false,
message: 'Please select'
}],
})(
<Switch checkedChildren={<Icon type="check"/>}
unCheckedChildren={<Icon type="close"/>} defaultChecked/>
)}
</Form.Item>
<Divider/>
<Form.Item {...formItemLayout} label="Tags">
{getFieldDecorator('tags', {
rules: [{
required: false,
required: true,
message: 'Please select tags'
}],
})(
@ -438,7 +366,7 @@ class AddNewAppFormComponent extends React.Component {
</Select>
)}
</Form.Item>
<Form.Item {...formItemLayout} label="Meta Daa">
<Form.Item {...formItemLayout} label="Meta Data">
<InputGroup>
<Row gutter={8}>
<Col span={10}>
@ -453,46 +381,39 @@ class AddNewAppFormComponent extends React.Component {
</Row>
</InputGroup>
</Form.Item>
<Form.Item wrapperCol={{span: 12, offset: 5}}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</div>
</Col>
<Col span={12} style={{paddingLeft: 20}}>
<Form.Item label="Application">
<div className="dropbox">
<p>Release Data</p>
{formConfig.specificElements.hasOwnProperty("binaryFile") && (
<Form.Item {...formItemLayout} label="Application">
{getFieldDecorator('binaryFile', {
valuePropName: 'fileList',
valuePropName: 'binaryFile',
getValueFromEvent: this.normFile,
required: false,
message: 'Please select tags'
required: true,
message: 'Please select application'
})(
<Upload.Dragger
name="files"
<Upload
name="binaryFile"
onChange={this.handleBinaryFileChange}
beforeUpload={() => false}
multiple={false}
>
<p className="ant-upload-drag-icon">
<Icon type="inbox"/>
</p>
<p className="ant-upload-text">Click or drag file to this area
to upload</p>
<p className="ant-upload-hint">Support for a single or bulk
upload.</p>
</Upload.Dragger>,
{binaryFiles.length !== 1 && (
<Button>
<Icon type="upload"/> Click to upload
</Button>
)}
</Upload>,
)}
</div>
</Form.Item>
)}
<Row>
<Col span={12}>
<Form.Item label="Icon">
<Form.Item {...formItemLayout} label="Icon">
{getFieldDecorator('icon', {
valuePropName: 'icon',
getValueFromEvent: this.normFile,
required: false,
required: true,
message: 'Please select a icon'
})(
<Upload
@ -500,28 +421,26 @@ class AddNewAppFormComponent extends React.Component {
onChange={this.handleIconChange}
beforeUpload={() => false}
>
{icons.length !== 1 && (
<Button>
<Icon type="upload"/> Click to upload
</Button>
)}
</Upload>,
)}
</Form.Item>
</Col>
</Row>
<Row style={{marginTop: 40}}>
<Col span={24}>
<Form.Item label="Screenshots">
</Col>
</Row>
<Form.Item {...formItemLayout} label="Screenshots">
{getFieldDecorator('screenshots', {
valuePropName: 'icon',
getValueFromEvent: this.normFile,
required: false,
required: true,
message: 'Please select a icon'
})(
<Upload
@ -541,22 +460,110 @@ class AddNewAppFormComponent extends React.Component {
</Upload>,
)}
</Form.Item>
</Col>
</Row>
{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', {
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="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>
<Form.Item {...formItemLayout} label="Price">
{getFieldDecorator('price', {
rules: [{
required: false
}],
})(
<Input prefix="$" placeholder="00.00"/>
)}
</Form.Item>
<Form.Item {...formItemLayout} label="Is Shared?">
{getFieldDecorator('isSharedWithAllTenants', {
rules: [{
required: true,
message: 'Please select'
}],
initialValue: false
})(
<Switch checkedChildren={<Icon type="check"/>}
unCheckedChildren={<Icon type="close"/>}
/>
)}
</Form.Item>
</Col>
</Row>
<Form.Item style={{float: "right"}}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
</Card>
</Col>
</Row>
</Spin>
</div>
);
}
}
const AddNewAppForm = Form.create({name: 'add-new-app'})(AddNewAppFormComponent);
const AddNewAppForm = withRouter(Form.create({name: 'add-new-app'})(AddNewAppFormComponent));
export default AddNewAppForm;

@ -6,9 +6,11 @@ import Login from "./pages/Login";
import Dashboard from "./pages/dashboard/Dashboard";
import Apps from "./pages/dashboard/apps/Apps";
import Release from "./pages/dashboard/apps/release/Release";
import AddNewApp from "./pages/dashboard/add-new-app/AddNewApp";
import AddNewEnterpriseApp from "./pages/dashboard/add-new-app/AddNewEnterpriseApp";
import Mange from "./pages/dashboard/manage/Manage";
import './index.css';
import AddNewPublicApp from "./pages/dashboard/add-new-app/AddNewPublicApp";
import AddNewWebClip from "./pages/dashboard/add-new-app/AddNewWebClip";
const routes = [
@ -34,17 +36,17 @@ const routes = [
},
{
path: '/publisher/add-new-app/enterprise',
component: AddNewApp,
component: AddNewEnterpriseApp,
exact: true
},
{
path: '/publisher/add-new-app/public',
component: AddNewApp,
component: AddNewPublicApp,
exact: true
},
{
path: '/publisher/add-new-app/web-clip',
component: AddNewApp,
component: AddNewWebClip,
exact: true
},
{

@ -1,153 +0,0 @@
import React from "react";
import "antd/dist/antd.css";
import {
PageHeader,
Typography,
Card,
Steps,
Button,
message,
Row,
Col,
Tag,
Tooltip,
Input,
Icon,
Select,
Switch,
Form,
Upload,
Divider
} from "antd";
import axios from "axios";
import AddNewAppForm from "../../../components/new-app/AddNewAppForm"
import config from "../../../../public/conf/config.json";
const Paragraph = Typography;
const Dragger = Upload.Dragger;
const props = {
name: 'file',
multiple: false,
action: '//jsonplaceholder.typicode.com/posts/',
onChange(info) {
const status = info.file.status;
if (status !== 'uploading') {
console.log(info.file, info.fileList);
}
if (status === 'done') {
message.success(`${info.file.name} file uploaded successfully.`);
} else if (status === 'error') {
message.error(`${info.file.name} file upload failed.`);
}
},
};
//
// const steps = [{
// title: 'First',
// content: Step1
// }, {
// title: 'Second',
// content: Step2,
// }, {
// title: 'Last',
// content: Step3,
// }];
const {Option} = Select;
const {TextArea} = Input;
const InputGroup = Input.Group;
const formItemLayout = {
labelCol: {
span: 4,
},
wrapperCol: {
span: 20,
},
};
class AddNewApp extends React.Component {
constructor(props) {
super(props);
this.state = {
current: 0,
categories: []
};
}
componentDidMount() {
// this.getCategories();
}
next() {
const current = this.state.current + 1;
this.setState({current});
}
prev() {
const current = this.state.current - 1;
this.setState({current});
}
getCategories = () => {
axios.get(
config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/categories",
{
headers: {'X-Platform': config.serverConfig.platform}
}).then(res => {
if (res.status === 200) {
let categories = JSON.parse(res.data.data);
this.setState({
categories: categories,
loading: false
});
}
}).catch((error) => {
if (error.response.status === 401) {
window.location.href = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + '/publisher/login';
} else {
message.warning('Something went wrong');
}
this.setState({
loading: false
});
});
};
handleCategoryChange = (value) => {
console.log(`selected ${value}`);
};
render() {
const {categories} = this.state;
return (
<div>
<PageHeader
title="Add New App"
>
<div className="wrap">
<div className="content">
<Paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempo.
</Paragraph>
</div>
</div>
</PageHeader>
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
<AddNewAppForm/>
</div>
</div>
);
}
}
export default AddNewApp;

@ -0,0 +1,62 @@
import React from "react";
import "antd/dist/antd.css";
import {
PageHeader,
Typography
} from "antd";
import AddNewAppForm from "../../../components/new-app/AddNewAppForm";
const Paragraph = Typography;
const formConfig = {
installationType: "ENTERPRISE",
endpoint: "/ent-app",
jsonPayloadName:"application",
releaseWrapperName: "entAppReleaseWrappers",
specificElements: {
binaryFile: {
required: true
}
}
};
class AddNewEnterpriseApp extends React.Component {
constructor(props) {
super(props);
this.state = {
current: 0,
categories: []
};
}
componentDidMount() {
// this.getCategories();
}
render() {
return (
<div>
<PageHeader
title="Add New Enterprise App"
>
<div className="wrap">
<div className="content">
<Paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempo.
</Paragraph>
</div>
</div>
</PageHeader>
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
<AddNewAppForm formConfig={formConfig}/>
</div>
</div>
);
}
}
export default AddNewEnterpriseApp;

@ -0,0 +1,65 @@
import React from "react";
import "antd/dist/antd.css";
import {
PageHeader,
Typography
} from "antd";
import AddNewAppForm from "../../../components/new-app/AddNewAppForm";
const Paragraph = Typography;
const formConfig = {
installationType: "PUBLIC",
endpoint: "/public-app",
jsonPayloadName:"public-app",
releaseWrapperName: "publicAppReleaseWrappers",
specificElements: {
packageName : {
required: true
},
version : {
required: true
}
}
};
class AddNewEnterpriseApp extends React.Component {
constructor(props) {
super(props);
this.state = {
current: 0,
categories: []
};
}
componentDidMount() {
// this.getCategories();
}
render() {
return (
<div>
<PageHeader
title="Add New Public App"
>
<div className="wrap">
<div className="content">
<Paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempo.
</Paragraph>
</div>
</div>
</PageHeader>
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
<AddNewAppForm formConfig={formConfig}/>
</div>
</div>
);
}
}
export default AddNewEnterpriseApp;

@ -0,0 +1,65 @@
import React from "react";
import "antd/dist/antd.css";
import {
PageHeader,
Typography
} from "antd";
import AddNewAppForm from "../../../components/new-app/AddNewAppForm";
const Paragraph = Typography;
const formConfig = {
installationType: "WEB_CLIP",
endpoint: "/web-app",
jsonPayloadName:"webapp",
releaseWrapperName: "webAppReleaseWrappers",
specificElements: {
url : {
required: true
},
version : {
required: true
}
}
};
class AddNewEnterpriseApp extends React.Component {
constructor(props) {
super(props);
this.state = {
current: 0,
categories: []
};
}
componentDidMount() {
// this.getCategories();
}
render() {
return (
<div>
<PageHeader
title="Add New Web Clip"
>
<div className="wrap">
<div className="content">
<Paragraph>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempo.
</Paragraph>
</div>
</div>
</PageHeader>
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
<AddNewAppForm formConfig={formConfig}/>
</div>
</div>
);
}
}
export default AddNewEnterpriseApp;
Loading…
Cancel
Save