mirror of
https://repository.entgra.net/community/device-mgt-core.git
synced 2025-10-06 02:01:45 +00:00
Added form validation and image visualization to application and platform create. Removed hash router and used browser router.
This commit is contained in:
parent
89b4e6dc10
commit
b70bf91f3a
@ -25,8 +25,8 @@
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/publisher/manifest.json">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/publisher/images/favicon.png">
|
||||
<link rel="manifest" href="manifest.json">
|
||||
<link rel="shortcut icon" href="images/favicon.png">
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
@ -39,6 +39,7 @@
|
||||
<title>WSO2 IoT App Publisher</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src='./dist/index.js'></script>
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
|
||||
@ -18,8 +18,8 @@
|
||||
|
||||
import './App.css';
|
||||
import React, {Component} from 'react';
|
||||
import createHistory from 'history/createHashHistory';
|
||||
import {HashRouter as Router, Redirect, Route, Switch} from 'react-router-dom'
|
||||
import createHistory from 'history/createBrowserHistory';
|
||||
import {BrowserRouter as Router, Redirect, Route, Switch} from 'react-router-dom'
|
||||
import {
|
||||
ApplicationCreate,
|
||||
ApplicationListing,
|
||||
@ -41,6 +41,9 @@ const history = createHistory({basename: '/publisher'});
|
||||
* The Router and Route is used for navigation.
|
||||
* We specify the component which needs to be rendered for an URL.
|
||||
* Ex: When navigate to publisher/overview, the overview component will be rendered inside the main layout.
|
||||
*
|
||||
* HashRouter is used because the other router types need the server to serve those urls. In hashRouter, server does
|
||||
* not want to serve the URL.
|
||||
* */
|
||||
|
||||
class Base extends Component {
|
||||
@ -63,9 +66,9 @@ class Base extends Component {
|
||||
<Route exact path={"/assets/platforms"} component={PlatformListing}/>
|
||||
<Route exact path={"/assets/platforms/create"} component={PlatformCreate}/>
|
||||
<Route exact path={"/assets/apps/:app"} />
|
||||
<Route exact path={"/assets/apps/edit/:app"} />
|
||||
<Route exact path={"/assets/apps/:app/edit"} />
|
||||
<Route exact path={"/assets/platforms/:platform"}/>
|
||||
<Route exact path={"/assets/platforms/edit/:platform"}/>
|
||||
<Route exact path={"/assets/platforms/:platform/edit"}/>
|
||||
<Route exact path={"/assets/reviews"}/>
|
||||
<Route exact path={"/assets/reviews/:review"}/>
|
||||
<Route component={NotFound}/>
|
||||
@ -80,6 +83,9 @@ class Base extends Component {
|
||||
|
||||
/**
|
||||
* This component is referred by the index.js to initiate the application.
|
||||
* TODO: Currently the URL shows like https://localhost:9443/publisher/#/publisher/assets/apps/create. this needs to
|
||||
* be fixed as https://localhost:9443/publisher/#/assets/apps/create
|
||||
*
|
||||
* */
|
||||
class Publisher extends Component {
|
||||
render() {
|
||||
|
||||
@ -16,12 +16,11 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, {Component} from 'react';
|
||||
import Dialog from 'material-ui/Dialog';
|
||||
import {withRouter} from 'react-router-dom';
|
||||
import {Step1, Step2, Step3} from './Forms';
|
||||
import FlatButton from 'material-ui/FlatButton';
|
||||
import {Step1, Step2, Step3} from './CreateSteps';
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
import {Card, CardActions, CardTitle} from 'material-ui/Card';
|
||||
import {Step, StepLabel, Stepper,} from 'material-ui/Stepper';
|
||||
@ -56,6 +55,7 @@ class ApplicationCreate extends Component {
|
||||
* Handles next button click event.
|
||||
* */
|
||||
handleNext = () => {
|
||||
console.log("Handle Next");
|
||||
const {stepIndex} = this.state;
|
||||
this.setState({
|
||||
stepIndex: stepIndex + 1,
|
||||
@ -98,7 +98,7 @@ class ApplicationCreate extends Component {
|
||||
let tmpStepData = this.state.stepData;
|
||||
tmpStepData.push({step: step, data: data});
|
||||
|
||||
this.setState({stepData: tmpStepData})
|
||||
this.setState({stepData: tmpStepData}, this.handleNext())
|
||||
};
|
||||
|
||||
/**
|
||||
@ -180,7 +180,7 @@ class ApplicationCreate extends Component {
|
||||
|
||||
return (
|
||||
<div className="middle" style={{width: '95%', height: '100%', marginTop: '1%'}}>
|
||||
<Card>
|
||||
<Card style={{maxHeight: '700px', overflow: 'auto'}}>
|
||||
<CardTitle title="Create Application"/>
|
||||
|
||||
{/**
|
||||
|
||||
@ -125,8 +125,6 @@ class ApplicationListing extends Component {
|
||||
return dataItem.applicationName.includes(word);
|
||||
});
|
||||
} else {
|
||||
console.log("no")
|
||||
console.log(this.data)
|
||||
searchedData = this.data;
|
||||
}
|
||||
|
||||
@ -153,7 +151,7 @@ class ApplicationListing extends Component {
|
||||
}
|
||||
|
||||
_onRowClick(id) {
|
||||
console.log(id)
|
||||
this.props.history.push("apps/"+id);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@ -44,10 +44,16 @@ class Step1 extends Component {
|
||||
stepIndex: 0,
|
||||
store: 1,
|
||||
platform: 1,
|
||||
stepData: []
|
||||
stepData: [],
|
||||
title: "",
|
||||
titleError: ""
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
//Get the list of available platforms and set to the state.
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the handleNext function in Create component.
|
||||
* */
|
||||
@ -59,8 +65,11 @@ class Step1 extends Component {
|
||||
* Persist the current form data to the state.
|
||||
* */
|
||||
_setStepData() {
|
||||
this.props.setData("step1", {step: "Dfds"});
|
||||
this._handleNext.bind(this);
|
||||
var step = {
|
||||
store: this.state.store,
|
||||
platform: this.state.platform
|
||||
};
|
||||
this.props.setData("step1", {step: step});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -71,13 +80,13 @@ class Step1 extends Component {
|
||||
* */
|
||||
_handleClick() {
|
||||
this._setStepData();
|
||||
this._handleNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers when changing the Platform selection.
|
||||
* */
|
||||
_onChangePlatform = (event, index, value) => {
|
||||
console.log(value);
|
||||
this.setState({platform: value});
|
||||
};
|
||||
|
||||
@ -88,6 +97,13 @@ class Step1 extends Component {
|
||||
this.setState({store: value});
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggers when user types on Title text field.
|
||||
* */
|
||||
_onChangeTitle = (event, value) => {
|
||||
this.setState({title: value});
|
||||
};
|
||||
|
||||
render() {
|
||||
const contentStyle = {margin: '0 16px'};
|
||||
return (
|
||||
@ -95,11 +111,6 @@ class Step1 extends Component {
|
||||
<div style={contentStyle}>
|
||||
<div>
|
||||
<div>
|
||||
<TextField
|
||||
hintText="Enter a title for your application."
|
||||
floatingLabelText="Title*"
|
||||
floatingLabelFixed={true}
|
||||
/><br/>
|
||||
<SelectField
|
||||
floatingLabelText="Store Type*"
|
||||
value={this.state.store}
|
||||
@ -117,7 +128,7 @@ class Step1 extends Component {
|
||||
>
|
||||
<MenuItem value={1} primaryText="Android"/>
|
||||
<MenuItem value={2} primaryText="iOS"/>
|
||||
<MenuItem value={3} primaryText="Web"/>
|
||||
<MenuItem value={{name: "Web", id:3}} primaryText="Web"/>
|
||||
</SelectField>
|
||||
</div>
|
||||
|
||||
@ -0,0 +1,489 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import Chip from 'material-ui/Chip';
|
||||
import Dropzone from 'react-dropzone';
|
||||
import React, {Component} from 'react';
|
||||
import MenuItem from 'material-ui/MenuItem';
|
||||
import TextField from 'material-ui/TextField';
|
||||
import FlatButton from 'material-ui/FlatButton';
|
||||
import IconButton from 'material-ui/IconButton';
|
||||
import SelectField from 'material-ui/SelectField';
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
import Clear from 'material-ui/svg-icons/content/clear';
|
||||
import {GridList, GridTile} from 'material-ui/GridList';
|
||||
|
||||
/**
|
||||
* The Second step of application create wizard.
|
||||
* This contains following components.
|
||||
* * App Title
|
||||
* * Short Description
|
||||
* * Application Description
|
||||
* * Application Visibility
|
||||
* * Application Tags : {Used Material UI Chip component}
|
||||
* * Application Category.
|
||||
* * Platform Specific properties.
|
||||
* * Screenshots
|
||||
* * Banner
|
||||
* * Icon
|
||||
*
|
||||
* Parent Component: Create
|
||||
* Props:
|
||||
* * handleNext : {type: function, Invokes handleNext function in Parent.}
|
||||
* * handlePrev : {type: function, Invokes handlePrev function in Parent}
|
||||
* * setData : {type: function, Invokes setStepData function in Parent}
|
||||
* * removeData : {type: Invokes removeStepData function in Parent}
|
||||
* */
|
||||
class Step2 extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
tags: [],
|
||||
defValue: "",
|
||||
category: 0,
|
||||
visibility: 0,
|
||||
errors: {},
|
||||
title: "",
|
||||
shortDescription: "",
|
||||
description: "",
|
||||
banner: [],
|
||||
screenshots: [],
|
||||
icon: []
|
||||
};
|
||||
|
||||
this.styles = {
|
||||
chip: {
|
||||
margin: 4,
|
||||
},
|
||||
wrapper: {
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a tag on Enter key press and set it to the state.
|
||||
* Clears the tags text field.
|
||||
* Chip gets two parameters: Key and value.
|
||||
* */
|
||||
_addTags(event) {
|
||||
let tags = this.state.tags;
|
||||
if (event.charCode === 13) {
|
||||
event.preventDefault();
|
||||
tags.push({key: Math.floor(Math.random() * 1000), value: event.target.value});
|
||||
this.setState({tags, defValue: ""});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value for tag.
|
||||
* */
|
||||
_handleTagChange(event) {
|
||||
let defaultValue = this.state.defValue;
|
||||
defaultValue = event.target.value;
|
||||
this.setState({defValue: defaultValue})
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the handleNext function in Create component.
|
||||
* */
|
||||
_handleNext() {
|
||||
let fields = [{name: "Title", value: this.state.title},
|
||||
{name: "Short Description", value: this.state.shortDescription},
|
||||
{name: "Description", value: this.state.description},
|
||||
{name: "Banner", value: this.state.banner},
|
||||
{name: "Screenshots", value: this.state.screenshots},
|
||||
{name: "Icon", value: this.state.icon}];
|
||||
this._validate(fields);
|
||||
// this.props.handleNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the handlePrev function in Create component.
|
||||
* */
|
||||
_handlePrev() {
|
||||
this.props.handlePrev();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles Chip delete function.
|
||||
* Removes the tag from state.tags
|
||||
* */
|
||||
_handleRequestDelete = (key) => {
|
||||
this.chipData = this.state.tags;
|
||||
const chipToDelete = this.chipData.map((chip) => chip.key).indexOf(key);
|
||||
this.chipData.splice(chipToDelete, 1);
|
||||
this.setState({tags: this.chipData});
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates Chip array from state.tags.
|
||||
* */
|
||||
_renderChip(data) {
|
||||
return (
|
||||
<Chip
|
||||
key={data.key}
|
||||
onRequestDelete={() => this._handleRequestDelete(data.key)}
|
||||
style={this.styles.chip}
|
||||
>
|
||||
{data.value}
|
||||
</Chip>
|
||||
);
|
||||
}
|
||||
|
||||
_onVisibilitySelect = (event, index, value) => {
|
||||
console.log(value);
|
||||
let comp = <SelectField> <MenuItem value={0} primaryText="Public"/>
|
||||
<MenuItem value={1} primaryText="Roles"/>
|
||||
<MenuItem value={2} primaryText="Devices"/> </SelectField>;
|
||||
if (value === 1) {
|
||||
this.setState({visibilityComponent: comp});
|
||||
} else if (value === 2) {
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate the form.
|
||||
* */
|
||||
_validate(fields) {
|
||||
let errors = {};
|
||||
let errorsPresent = false;
|
||||
fields.forEach(function (field) {
|
||||
switch (field.name) {
|
||||
case 'Title': {
|
||||
if (field.value === "") {
|
||||
errors[field.name] = field.name + " is required!";
|
||||
errorsPresent = true;
|
||||
} else {
|
||||
errorsPresent = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'Short Description': {
|
||||
if (field.value === "") {
|
||||
errors[field.name] = field.name + " is required!";
|
||||
errorsPresent = true;
|
||||
} else {
|
||||
errorsPresent = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'Description': {
|
||||
if (field.value === "") {
|
||||
errors[field.name] = field.name + " is required!";
|
||||
errorsPresent = true;
|
||||
} else {
|
||||
errorsPresent = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'Banner': {
|
||||
if (field.value.length === 0) {
|
||||
errors[field.name] = field.name + " is required!";
|
||||
errorsPresent = true;
|
||||
} else {
|
||||
errorsPresent = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'Icon': {
|
||||
if (field.value.length === 0) {
|
||||
errors[field.name] = field.name + " is required!";
|
||||
errorsPresent = true;
|
||||
} else {
|
||||
errorsPresent = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'Screenshots': {
|
||||
if (field.value.length < 3) {
|
||||
errors[field.name] = "3 " +field.name + " are required!";
|
||||
errorsPresent = true;
|
||||
} else {
|
||||
errorsPresent = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log(errorsPresent);
|
||||
if (!errorsPresent) {
|
||||
this._setStepData();
|
||||
} else {
|
||||
this.setState({errors: errors}, console.log(errors));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an object with the current step data and persist in the parent.
|
||||
* */
|
||||
_setStepData() {
|
||||
let stepData = {
|
||||
title: this.state.title,
|
||||
description: this.state.description,
|
||||
shortDescription: this.state.shortDescription,
|
||||
tags: this.state.tags,
|
||||
banner: this.state.banner,
|
||||
screenshots: this.state.screenshots,
|
||||
icon: this.state.icon
|
||||
};
|
||||
|
||||
this.props.setData("step2", {step: stepData});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set text field values to state.
|
||||
* */
|
||||
_onTextFieldChange(event, value) {
|
||||
let field = event.target.id;
|
||||
switch (field) {
|
||||
case "title": {
|
||||
this.setState({title: value});
|
||||
break;
|
||||
}
|
||||
case "shortDescription": {
|
||||
this.setState({shortDescription: value});
|
||||
break;
|
||||
}
|
||||
case "description": {
|
||||
this.setState({description: value});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removed user uploaded banner.
|
||||
* */
|
||||
_removeBanner(event, d) {
|
||||
console.log(event, d);
|
||||
this.setState({banner: []});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes uploaded icon.
|
||||
* */
|
||||
_removeIcon(event) {
|
||||
this.setState({icon: []});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes selected screenshot.
|
||||
* */
|
||||
_removeScreenshot(event) {
|
||||
console.log(event.target)
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log(this.state.visibilityComponent);
|
||||
const contentStyle = {margin: '0 16px'};
|
||||
return (
|
||||
<div style={contentStyle}>
|
||||
<div>
|
||||
<div>
|
||||
<TextField
|
||||
id="title"
|
||||
hintText="Enter a title for your application."
|
||||
errorText={this.state.errors["Title"]}
|
||||
floatingLabelText="Title*"
|
||||
floatingLabelFixed={true}
|
||||
onChange={this._onTextFieldChange.bind(this)}
|
||||
/><br/>
|
||||
<TextField
|
||||
id="shortDescription"
|
||||
hintText="Enter a short description for your application."
|
||||
errorText={this.state.errors["Short Description"]}
|
||||
floatingLabelText="Short Description*"
|
||||
floatingLabelFixed={true}
|
||||
multiLine={true}
|
||||
rows={2}
|
||||
onChange={this._onTextFieldChange.bind(this)}
|
||||
|
||||
/><br/>
|
||||
<TextField
|
||||
id="description"
|
||||
errorText={this.state.errors["Description"]}
|
||||
hintText="Enter the description."
|
||||
floatingLabelText="Description*"
|
||||
floatingLabelFixed={true}
|
||||
multiLine={true}
|
||||
rows={4}
|
||||
onChange={this._onTextFieldChange.bind(this)}
|
||||
/><br/>
|
||||
<SelectField
|
||||
floatingLabelText="Visibility*"
|
||||
value={this.state.visibility}
|
||||
floatingLabelFixed={true}
|
||||
onChange={this._onVisibilitySelect.bind(this)}
|
||||
>
|
||||
<MenuItem value={0} primaryText="Public"/>
|
||||
<MenuItem value={1} primaryText="Roles"/>
|
||||
<MenuItem value={2} primaryText="Devices"/>
|
||||
</SelectField><br/>
|
||||
<TextField
|
||||
id="tags"
|
||||
errorText={this.state.errors["tags"]}
|
||||
hintText="Enter application tags.."
|
||||
floatingLabelText="Tags*"
|
||||
floatingLabelFixed={true}
|
||||
value={this.state.defValue}
|
||||
onChange={this._handleTagChange.bind(this)}
|
||||
onKeyPress={this._addTags.bind(this)}
|
||||
/><br/>
|
||||
<div style={this.styles.wrapper}>
|
||||
{this.state.tags.map(this._renderChip, this)}
|
||||
</div>
|
||||
<br/>
|
||||
<SelectField
|
||||
floatingLabelText="Category*"
|
||||
value={this.state.category}
|
||||
floatingLabelFixed={true}
|
||||
>
|
||||
<MenuItem value={0} primaryText="Business"/>
|
||||
</SelectField> <br/>
|
||||
{/*Platform Specific Properties.*/}
|
||||
<div style={{border: 'solid #BDBDBD 1px'}}>
|
||||
<p style={{color: '#BDBDBD'}}>Platform Specific Properties</p>
|
||||
</div>
|
||||
<br/>
|
||||
<div>
|
||||
<p style={{color: '#f44336'}}>{this.state.errors["Banner"]}</p>
|
||||
<p style={{color: '#BDBDBD'}}>Banner*:</p>
|
||||
<GridList style={{
|
||||
display: 'flex',
|
||||
flexWrap: 'nowrap',
|
||||
overflowX: 'auto',
|
||||
}} cols={1.1}>
|
||||
{this.state.banner.map((tile) => (
|
||||
<GridTile key={Math.floor(Math.random() * 1000)}
|
||||
title={tile.name}
|
||||
actionIcon={
|
||||
<IconButton onClick={this._removeBanner.bind(this)}>
|
||||
<Clear />
|
||||
</IconButton>}>
|
||||
<img src={tile.preview}/></GridTile>
|
||||
))}
|
||||
{this.state.banner.length === 0 ?
|
||||
<Dropzone style={{width: '300px', height: '150px', border: 'dashed #BDBDBD 1px'}}
|
||||
accept="image/jpeg, image/png"
|
||||
onDrop={(banner, rejected) => {
|
||||
this.setState({banner, rejected});
|
||||
}}>
|
||||
<p style={{margin: '70px 40px 40px 150px'}}>+</p>
|
||||
</Dropzone> : <div />}
|
||||
|
||||
</GridList>
|
||||
|
||||
</div>
|
||||
<br/>
|
||||
<div>
|
||||
<p style={{color: '#f44336'}}>{this.state.errors["Screenshots"]}</p>
|
||||
<p style={{color: '#BDBDBD'}}>Screenshots*:</p>
|
||||
<GridList style={{
|
||||
display: 'flex',
|
||||
flexWrap: 'nowrap',
|
||||
overflowX: 'auto',
|
||||
}} cols={1.1}>
|
||||
{this.state.screenshots.map((file) => (
|
||||
<GridTile key={Math.floor(Math.random() * 1000)}
|
||||
title={file[0].name}
|
||||
actionIcon={
|
||||
<IconButton onClick={this._removeScreenshot.bind(this)}>
|
||||
<Clear/>
|
||||
</IconButton>}>
|
||||
<img src={file[0].preview}/></GridTile>
|
||||
))}
|
||||
{this.state.screenshots.length < 3 ?
|
||||
<Dropzone style={{width: '150px', height: '150px', border: 'dashed #BDBDBD 1px'}}
|
||||
accept="image/jpeg, image/png"
|
||||
onDrop={(screenshots, rejected) => {
|
||||
let tmpScreenshots = this.state.screenshots;
|
||||
tmpScreenshots.push(screenshots);
|
||||
this.setState({
|
||||
screenshots: tmpScreenshots});
|
||||
}}>
|
||||
<p style={{margin: '70px 40px 70px 70px'}}>+</p>
|
||||
</Dropzone> : <div />}
|
||||
</GridList>
|
||||
</div>
|
||||
<br/>
|
||||
<div>
|
||||
<p style={{color: '#f44336'}}>{this.state.errors["Icon"]}</p>
|
||||
<p style={{color: '#BDBDBD'}}>Icon*:</p>
|
||||
<GridList style={{
|
||||
display: 'flex',
|
||||
flexWrap: 'nowrap',
|
||||
overflowX: 'auto',
|
||||
}} cols={1.1}>
|
||||
{this.state.icon.map((tile) => (
|
||||
<GridTile key={Math.floor(Math.random() * 1000)}
|
||||
title={tile.name}
|
||||
actionIcon={
|
||||
<IconButton onClick={this._removeIcon.bind(this)}>
|
||||
<Clear />
|
||||
</IconButton>}>
|
||||
<img src={tile.preview}/></GridTile>
|
||||
))}
|
||||
{this.state.icon.length === 0 ?
|
||||
<Dropzone style={{width: '150px', height: '150px', border: 'dashed #BDBDBD 1px'}}
|
||||
accept="image/jpeg, image/png"
|
||||
onDrop={(icon, rejected) => {this.setState({icon, rejected});}}>
|
||||
<p style={{margin: '70px 40px 70px 70px'}}>+</p>
|
||||
</Dropzone> : <div />}
|
||||
</GridList>
|
||||
</div>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
<div style={{marginTop: 12}}>
|
||||
<FlatButton
|
||||
label="< Back"
|
||||
disabled={false}
|
||||
onClick={this._handlePrev.bind(this)}
|
||||
style={{marginRight: 12}}
|
||||
/>
|
||||
<RaisedButton
|
||||
label="Next >"
|
||||
primary={true}
|
||||
onClick={this._handleNext.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Step2.prototypes = {
|
||||
handleNext: PropTypes.func,
|
||||
handlePrev: PropTypes.func,
|
||||
setData: PropTypes.func,
|
||||
removeData: PropTypes.func
|
||||
};
|
||||
|
||||
export default Step2;
|
||||
@ -1,240 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||
*
|
||||
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||
* Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import Chip from 'material-ui/Chip';
|
||||
import Dropzone from 'react-dropzone';
|
||||
import React, {Component} from 'react';
|
||||
import MenuItem from 'material-ui/MenuItem';
|
||||
import TextField from 'material-ui/TextField';
|
||||
import FlatButton from 'material-ui/FlatButton';
|
||||
import SelectField from 'material-ui/SelectField';
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
|
||||
/**
|
||||
* The Second step of application create wizard.
|
||||
* This contains following components.
|
||||
* * App Title
|
||||
* * Short Description
|
||||
* * Application Description
|
||||
* * Application Visibility
|
||||
* * Application Tags : {Used Material UI Chip component}
|
||||
* * Application Category.
|
||||
* * Platform Specific properties.
|
||||
* * Screenshots
|
||||
* * Banner
|
||||
* * Icon
|
||||
*
|
||||
* Parent Component: Create
|
||||
* Props:
|
||||
* * handleNext : {type: function, Invokes handleNext function in Parent.}
|
||||
* * handlePrev : {type: function, Invokes handlePrev function in Parent}
|
||||
* * setData : {type: function, Invokes setStepData function in Parent}
|
||||
* * removeData : {type: Invokes removeStepData function in Parent}
|
||||
* */
|
||||
class Step2 extends Component {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
tags: [],
|
||||
defValue: "",
|
||||
category: 1,
|
||||
errors: {}
|
||||
};
|
||||
|
||||
this.styles = {
|
||||
chip: {
|
||||
margin: 4,
|
||||
},
|
||||
wrapper: {
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a tag on Enter key press and set it to the state.
|
||||
* Clears the tags text field.
|
||||
* Chip gets two parameters: Key and value.
|
||||
* */
|
||||
_addTags(event) {
|
||||
let tags = this.state.tags;
|
||||
if (event.charCode === 13) {
|
||||
event.preventDefault();
|
||||
tags.push({key: Math.floor(Math.random() * 1000), value: event.target.value});
|
||||
this.setState({tags, defValue: ""});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value for tag.
|
||||
* */
|
||||
_handleTagChange(event) {
|
||||
let defaultValue = this.state.defValue;
|
||||
defaultValue = event.target.value;
|
||||
this.setState({defValue: defaultValue})
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the handleNext function in Create component.
|
||||
* */
|
||||
_handleNext() {
|
||||
this.props.handleNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the handlePrev function in Create component.
|
||||
* */
|
||||
_handlePrev() {
|
||||
this.props.handlePrev();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles Chip delete function.
|
||||
* Removes the tag from state.tags
|
||||
* */
|
||||
_handleRequestDelete = (key) => {
|
||||
this.chipData = this.state.tags;
|
||||
const chipToDelete = this.chipData.map((chip) => chip.key).indexOf(key);
|
||||
this.chipData.splice(chipToDelete, 1);
|
||||
this.setState({tags: this.chipData});
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates Chip array from state.tags.
|
||||
* */
|
||||
_renderChip(data) {
|
||||
return (
|
||||
<Chip
|
||||
key={data.key}
|
||||
onRequestDelete={() => this._handleRequestDelete(data.key)}
|
||||
style={this.styles.chip}
|
||||
>
|
||||
{data.value}
|
||||
</Chip>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const contentStyle = {margin: '0 16px'};
|
||||
return (
|
||||
<div style={contentStyle}>
|
||||
<div>
|
||||
<div>
|
||||
<TextField
|
||||
hintText="Enter a title for your application."
|
||||
errorText={this.state.errors["title"]}
|
||||
floatingLabelText="Title*"
|
||||
floatingLabelFixed={true}
|
||||
/><br/>
|
||||
<TextField
|
||||
hintText="Enter a short description for your application."
|
||||
errorText={this.state.errors["shortDesc"]}
|
||||
floatingLabelText="Short Description*"
|
||||
floatingLabelFixed={true}
|
||||
multiLine={true}
|
||||
rows={2}
|
||||
|
||||
/><br/>
|
||||
<TextField
|
||||
errorText={this.state.errors["description"]}
|
||||
hintText="Enter the description."
|
||||
floatingLabelText="Description*"
|
||||
floatingLabelFixed={true}
|
||||
multiLine={true}
|
||||
rows={4}
|
||||
/><br/>
|
||||
<TextField
|
||||
hintText="Select the application visibility"
|
||||
floatingLabelText="Visibility"
|
||||
floatingLabelFixed={true}
|
||||
/><br/>
|
||||
<TextField
|
||||
errorText={this.state.errors["tags"]}
|
||||
hintText="Enter application tags.."
|
||||
floatingLabelText="Tags*"
|
||||
floatingLabelFixed={true}
|
||||
value={this.state.defValue}
|
||||
onChange={this._handleTagChange.bind(this)}
|
||||
onKeyPress={this._addTags.bind(this)}
|
||||
/><br/>
|
||||
<div style={this.styles.wrapper}>
|
||||
{this.state.tags.map(this._renderChip, this)}
|
||||
</div>
|
||||
<br/>
|
||||
<SelectField
|
||||
floatingLabelText="Category*"
|
||||
value={this.state.category}
|
||||
floatingLabelFixed={true}
|
||||
>
|
||||
<MenuItem value={1} primaryText="Business"/>
|
||||
</SelectField> <br/>
|
||||
{/*Platform Specific Properties.*/}
|
||||
<div style={{border: 'solid #BDBDBD 1px'}}>
|
||||
<p style={{color:'#BDBDBD'}}>Platform Specific Properties</p>
|
||||
</div><br/>
|
||||
<div>
|
||||
<p style={{color:'#BDBDBD'}}>Screenshots*:</p>
|
||||
<Dropzone style={{width:'100px', height:'100px', border: 'dashed #BDBDBD 1px'}}>
|
||||
<p style={{margin: '40px 40px 40px 50px'}}>+</p>
|
||||
</Dropzone>
|
||||
</div><br/>
|
||||
<div>
|
||||
<p style={{color:'#BDBDBD'}}>Banner*:</p>
|
||||
<Dropzone style={{width:'100px', height:'100px', border: 'dashed #BDBDBD 1px'}}>
|
||||
<p style={{margin: '40px 40px 40px 50px'}}>+</p>
|
||||
</Dropzone>
|
||||
</div><br/>
|
||||
<div>
|
||||
<p style={{color:'#BDBDBD'}}>Icon*:</p>
|
||||
<Dropzone style={{width:'100px', height:'100px', border: 'dashed #BDBDBD 1px'}}>
|
||||
<p style={{margin: '40px 40px 40px 50px'}}>+</p>
|
||||
</Dropzone>
|
||||
</div><br/>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<div style={{marginTop: 12}}>
|
||||
<FlatButton
|
||||
label="< Back"
|
||||
disabled={false}
|
||||
onClick={this._handlePrev.bind(this)}
|
||||
style={{marginRight: 12}}
|
||||
/>
|
||||
<RaisedButton
|
||||
label="Next >"
|
||||
primary={true}
|
||||
onClick={this._handleNext.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Step2.prototypes = {
|
||||
handleNext: PropTypes.func,
|
||||
handlePrev: PropTypes.func,
|
||||
setData: PropTypes.func,
|
||||
removeData: PropTypes.func
|
||||
};
|
||||
|
||||
export default Step2;
|
||||
@ -26,6 +26,8 @@ import FlatButton from 'material-ui/FlatButton';
|
||||
import IconButton from 'material-ui/IconButton';
|
||||
import SelectField from 'material-ui/SelectField';
|
||||
import RaisedButton from 'material-ui/RaisedButton';
|
||||
import Clear from 'material-ui/svg-icons/content/clear';
|
||||
import {GridList, GridTile} from 'material-ui/GridList';
|
||||
import Close from 'material-ui/svg-icons/navigation/close';
|
||||
import {Card, CardActions, CardTitle} from 'material-ui/Card';
|
||||
import AddCircleOutline from 'material-ui/svg-icons/content/add-circle-outline';
|
||||
@ -53,6 +55,7 @@ class PlatformCreate extends Component {
|
||||
name: "",
|
||||
description: "",
|
||||
property: "",
|
||||
icon: [],
|
||||
propertyTypes: [
|
||||
{key: 0, value: 'String'},
|
||||
{key: 1, value: 'Number'},
|
||||
@ -148,6 +151,16 @@ class PlatformCreate extends Component {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the uploaded icon.
|
||||
* */
|
||||
_removeIcon(event) {
|
||||
this.setState({icon: []});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the user entered values in the form.
|
||||
* */
|
||||
_clearForm() {
|
||||
this.setState({enabled: true,
|
||||
allTenants: false,
|
||||
@ -249,10 +262,32 @@ class PlatformCreate extends Component {
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{/*<p style={{color: '#f44336'}}>{this.state.errors["Icon"]}</p>*/}
|
||||
<p style={{color: '#BDBDBD'}}>Platform Icon*:</p>
|
||||
<Dropzone style={{width: '100px', height: '100px', border: 'dashed #BDBDBD 1px'}}>
|
||||
<p style={{margin: '40px 40px 40px 50px', color: '#BDBDBD'}}>+</p>
|
||||
</Dropzone>
|
||||
<GridList style={{
|
||||
display: 'flex',
|
||||
flexWrap: 'nowrap',
|
||||
overflowX: 'auto',
|
||||
}} cols={1.1}>
|
||||
{this.state.icon.map((tile) => (
|
||||
<GridTile key={Math.floor(Math.random() * 1000)}
|
||||
title={tile.name}
|
||||
actionIcon={
|
||||
<IconButton onClick={this._removeIcon.bind(this)}>
|
||||
<Clear />
|
||||
</IconButton>}>
|
||||
<img src={tile.preview}/>
|
||||
</GridTile>
|
||||
))}
|
||||
{this.state.icon.length === 0 ?
|
||||
<Dropzone style={
|
||||
{width: '150px', height: '150px', border: 'dashed #BDBDBD 1px'}
|
||||
}
|
||||
accept="image/jpeg, image/png"
|
||||
onDrop={(icon, rejected) => {this.setState({icon, rejected})}}>
|
||||
<p style={{margin: '70px 40px 70px 70px'}}>+</p>
|
||||
</Dropzone> : <div />}
|
||||
</GridList>
|
||||
</div>
|
||||
<br/>
|
||||
<RaisedButton primary={true} label="Create"
|
||||
@ -268,11 +303,6 @@ class PlatformCreate extends Component {
|
||||
}
|
||||
|
||||
PlatformCreate.prototypes = {
|
||||
enabled: PropTypes.bool,
|
||||
allTenants: PropTypes.bool,
|
||||
files: PropTypes.array,
|
||||
platformProperties: PropTypes.object,
|
||||
handleToggle: PropTypes.func
|
||||
};
|
||||
|
||||
export default PlatformCreate;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user