Integrated reactstrap components for base and app-create.

merge-requests/7/head
Menaka Jayawardena 7 years ago
parent 7569773d60
commit db5d71b9a7

@ -10,6 +10,7 @@
"license": "Apache License 2.0", "license": "Apache License 2.0",
"dependencies": { "dependencies": {
"axios": "^0.16.2", "axios": "^0.16.2",
"bootstrap": "^4.0.0-alpha.6",
"flux": "^3.1.3", "flux": "^3.1.3",
"history": "^4.7.2", "history": "^4.7.2",
"latest-version": "^3.1.0", "latest-version": "^3.1.0",
@ -17,6 +18,8 @@
"prop-types": "^15.5.10", "prop-types": "^15.5.10",
"qs": "^6.5.0", "qs": "^6.5.0",
"react": "^15.6.1", "react": "^15.6.1",
"react-addons-css-transition-group": "^15.6.0",
"react-addons-transition-group": "^15.6.0",
"react-dom": "^15.6.1", "react-dom": "^15.6.1",
"react-dropzone": "^4.1.2", "react-dropzone": "^4.1.2",
"react-images-uploader": "^1.1.0", "react-images-uploader": "^1.1.0",
@ -26,7 +29,8 @@
"react-router-dom": "^4.2.2", "react-router-dom": "^4.2.2",
"react-scripts": "1.0.10", "react-scripts": "1.0.10",
"react-sliding-pane": "^1.2.3", "react-sliding-pane": "^1.2.3",
"react-tap-event-plugin": "^2.0.1" "react-tap-event-plugin": "^2.0.1",
"reactstrap": "^4.8.0"
}, },
"devDependencies": { "devDependencies": {
"babel-core": "^6.26.0", "babel-core": "^6.26.0",

@ -21,6 +21,8 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000"> <meta name="theme-color" content="#000000">
<link rel="stylesheet" type="text/css" href="./css/font-wso2.css">
<link rel="stylesheet" type="text/css" href="./themes/index.css">
<!-- <!--
manifest.json provides metadata used when your web app is added to the 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/ homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/

@ -25,13 +25,14 @@ import {BrowserRouter as Router, Redirect, Route, Switch} from 'react-router-dom
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import getMuiTheme from 'material-ui/styles/getMuiTheme'; import getMuiTheme from 'material-ui/styles/getMuiTheme';
import { import {
ApplicationCreate, ApplicationCreate,
ApplicationListing, ApplicationListing,
BaseLayout, BaseLayout,
Login, Login,
NotFound, NotFound,
PlatformCreate, PlatformCreate,
PlatformListing PlatformListing,
ApplicationEdit
} from './components'; } from './components';
@ -78,7 +79,7 @@ class Base extends Component {
if (this.state.user !== null) { if (this.state.user !== null) {
console.log("Have User."); console.log("Have User.");
return ( return (
<div className="container"> <div>
<BaseLayout user={this.state.user}> <BaseLayout user={this.state.user}>
<Switch> <Switch>
<Redirect exact path={"/"} to={"/assets/apps"}/> <Redirect exact path={"/"} to={"/assets/apps"}/>
@ -86,8 +87,8 @@ class Base extends Component {
<Route exact path={"/assets/apps/create"} component={ApplicationCreate}/> <Route exact path={"/assets/apps/create"} component={ApplicationCreate}/>
<Route exact path={"/assets/platforms"} component={PlatformListing}/> <Route exact path={"/assets/platforms"} component={PlatformListing}/>
<Route exact path={"/assets/platforms/create"} component={PlatformCreate}/> <Route exact path={"/assets/platforms/create"} component={PlatformCreate}/>
<Route exact path={"/assets/apps/:app"}/> {/*<Route exact path={"/assets/apps/:app"}/>*/}
<Route exact path={"/assets/apps/:app/edit"}/> <Route exact path={"/assets/apps/edit/:app"} component={ApplicationEdit}/>
<Route exact path={"/assets/platforms/:platform"}/> <Route exact path={"/assets/platforms/:platform"}/>
<Route exact path={"/assets/platforms/:platform/edit"}/> <Route exact path={"/assets/platforms/:platform/edit"}/>
<Route exact path={"/assets/reviews"}/> <Route exact path={"/assets/reviews"}/>
@ -151,27 +152,28 @@ class Publisher extends Component {
if (this.state.selectedType === "default") { if (this.state.selectedType === "default") {
let defaultTheme = require("material-ui/styles/baseThemes/" + this.state.selectedTheme); let defaultTheme = require("material-ui/styles/baseThemes/" + this.state.selectedTheme);
this.setState({ this.setState({
muiTheme : getMuiTheme(defaultTheme.default) muiTheme: getMuiTheme(defaultTheme.default)
}); });
} else { } else {
let customTheme = require("./themes/" + this.state.selectedTheme); let customTheme = require("./themes/" + this.state.selectedTheme);
this.setState({ this.setState({
muiTheme : getMuiTheme(customTheme.default) muiTheme: getMuiTheme(customTheme.default)
}); });
} }
} }
render() { render() {
return ( return (
<div className="App"> <div className="App">
<MuiThemeProvider muiTheme={this.state.muiTheme}> <MuiThemeProvider>
<Router basename="publisher" history={history}> <Router basename="publisher" history={history}>
<Switch> <Switch>
<Route path="/login" component={Login}/> <Route path="/login" component={Login}/>
<Route path="/logout" component={Login}/> <Route path="/logout" component={Login}/>
<Route component={Base}/> <Route component={Base}/>
</Switch> </Switch>
</Router> </Router>
</MuiThemeProvider> </MuiThemeProvider>
</div> </div>
); );

@ -137,10 +137,13 @@ class AuthHandler {
} }
static createAuthenticationHeaders(contentType) { static createAuthenticationHeaders(contentType) {
return { if (AuthHandler.getUser().getAuthToken()) {
"Authorization": "Bearer " + AuthHandler.getUser().getAuthToken(), return {
"Content-Type": contentType, "Authorization": "Bearer " + AuthHandler.getUser().getAuthToken(),
}; "Content-Type": contentType,
};
}
return "User not found";
}; };
} }

@ -48,6 +48,9 @@ export default class Helper {
return {application, images}; return {application, images};
} }
/**
* Creates a String array from tags array.
* */
static stringifyTags(tags) { static stringifyTags(tags) {
let tmpTags = []; let tmpTags = [];
for (let tag in tags) { for (let tag in tags) {

@ -22,11 +22,12 @@ import Dialog from 'material-ui/Dialog';
import {withRouter} from 'react-router-dom'; import {withRouter} from 'react-router-dom';
import FlatButton from 'material-ui/FlatButton'; import FlatButton from 'material-ui/FlatButton';
import AuthHandler from "../../api/authHandler"; import AuthHandler from "../../api/authHandler";
import {Step1, Step2, Step3} from './CreateSteps'; import {Step1, Step2, Step3, Step4} from './CreateSteps';
import RaisedButton from 'material-ui/RaisedButton'; import RaisedButton from 'material-ui/RaisedButton';
import ApplicationMgtApi from '../../api/applicationMgtApi'; import ApplicationMgtApi from '../../api/applicationMgtApi';
import {Card, CardActions, CardTitle} from 'material-ui/Card'; import {Card, CardActions, CardTitle} from 'material-ui/Card';
import {Step, StepLabel, Stepper,} from 'material-ui/Stepper'; import {Step, StepLabel, Stepper,} from 'material-ui/Stepper';
import {Button, Modal, InputGroup, ModalHeader, ModalBody, ModalFooter, Input, Label, Form, FormGroup} from 'reactstrap';
/** /**
* The App Create Component. * The App Create Component.
@ -48,6 +49,7 @@ class ApplicationCreate extends Component {
this.handleNo = this.handleNo.bind(this); this.handleNo = this.handleNo.bind(this);
this.handlePrev = this.handlePrev.bind(this); this.handlePrev = this.handlePrev.bind(this);
this.handleNext = this.handleNext.bind(this); this.handleNext = this.handleNext.bind(this);
this.close = this.close.bind(this);
this.state = { this.state = {
finished: false, finished: false,
stepIndex: 0, stepIndex: 0,
@ -56,17 +58,25 @@ class ApplicationCreate extends Component {
}; };
} }
componentWillReceiveProps(props, nextprops) {
this.setState({open: props.open})
}
componentWillMount() { componentWillMount() {
/** this.setState({open: this.props.open});
*Loading the theme files based on the the user-preference. }
*/
Theme.insertThemingScripts(this.scriptId); close() {
this.setState({open: false, stepIndex: 0})
} }
componentWillUnmount() { handleBack() {
Theme.removeThemingScripts(this.scriptId); let currentStep = this.state.stepIndex;
let nextStep = currentStep === 0 ? currentStep : currentStep - 1 ;
this.setState({stepIndex: nextStep}, console.log(this.state.stepIndex));
} }
/** /**
* Handles next button click event. * Handles next button click event.
* */ * */
@ -190,6 +200,15 @@ class ApplicationCreate extends Component {
removeData={this.removeStepData} removeData={this.removeStepData}
/> />
); );
case 3: {
return (
<Step4
handleNext={this.handleNext}
setData={this.setStepData}
removeData={this.removeStepData}
/>
)
}
default: default:
return <div/>; return <div/>;
} }
@ -198,69 +217,19 @@ class ApplicationCreate extends Component {
render() { render() {
const {finished, stepIndex} = this.state; const {finished, stepIndex} = this.state;
/**
* Defines the dialog box actions. [Yes][No]
* */
const actions = [
<FlatButton
label="Yes"
primary={true}
onClick={this.handleYes}
/>,
<FlatButton
label="No"
secondary={true}
onClick={this.handleNo}
/>,
];
return ( return (
<div className="middle createapplicationmiddle"> <div id="create-application-modal">
<Card className="creataapplicationcard"> <Modal isOpen={this.state.open} toggle={this.toggle} id="app-create-modal"
<CardTitle title="Create Application"/> backdrop={'static'}>
<ModalHeader toggle={this.toggle}><i style={{cursor: 'pointer'}} onClick={this.handlePrev}><strong>{'< '}</strong></i>Create Application</ModalHeader>
{/** <ModalBody id="modal-body-content">
* The stepper goes here. {this.getStepContent(this.state.stepIndex)}
*/} </ModalBody>
<CardActions> <ModalFooter>
<div className="createapplicationcardaction"> <Button color="secondary" onClick={this.close}>Cancel</Button>
<Stepper activeStep={stepIndex}> <Button color="primary" onClick={this.handleNext}>Continue</Button>{' '}
<Step> </ModalFooter>
<StepLabel>Select Application Platform</StepLabel> </Modal>
</Step>
<Step>
<StepLabel>Enter Application Details</StepLabel>
</Step>
<Step>
<StepLabel>Release</StepLabel>
</Step>
</Stepper>
<div className="createapplicationcontent">
{finished ? (
<div>
<p>Create App?</p>
<form>
<RaisedButton primary={true} label="Create" onClick={this.handleSubmit}/>
<FlatButton label="Cancel" onClick={this.handleCancel}/>
</form>
</div>
) : (
<div>
{this.getStepContent(stepIndex)}
</div>
)}
</div>
</div>
</CardActions>
</Card>
<Dialog
actions={actions}
modal={false}
open={this.state.isDialogOpen}
onRequestClose={this.handleNo}
>
Do you really want to cancel?
</Dialog>
</div>); </div>);
} }
} }

@ -19,11 +19,10 @@
import Theme from '../../theme'; import Theme from '../../theme';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {withRouter} from 'react-router-dom'; import {withRouter} from 'react-router-dom';
import TextField from 'material-ui/TextField';
import AuthHandler from "../../api/authHandler"; import AuthHandler from "../../api/authHandler";
import DataTable from '../UIComponents/DataTable';
import ApplicationMgtApi from '../../api/applicationMgtApi'; import ApplicationMgtApi from '../../api/applicationMgtApi';
import {Card, CardActions, CardTitle} from 'material-ui/Card'; import {Table} from 'reactstrap';
import Drawer from '../UIComponents/Drawer/Drawer'
/** /**
* The App Create Component. * The App Create Component.
@ -41,10 +40,15 @@ class ApplicationListing extends Component {
this.setData = this.setData.bind(this); this.setData = this.setData.bind(this);
this.sortData = this.sortData.bind(this); this.sortData = this.sortData.bind(this);
this.compare = this.compare.bind(this); this.compare = this.compare.bind(this);
this.handleButtonClick = this.handleButtonClick.bind(this);
this.state = { this.state = {
searchedApplications: [], searchedApplications: [],
applications: [], applications: [],
asc: true asc: true,
open: false,
application: {},
drawer: {},
appListStyle: {}
}; };
this.scriptId = "application-listing"; this.scriptId = "application-listing";
} }
@ -80,23 +84,48 @@ class ApplicationListing extends Component {
data_type: "string", data_type: "string",
sortable: false, sortable: false,
label: "Status" label: "Status"
},
{
data_id: "edit",
data_type: "button",
sortable: false,
label: ""
} }
]; ];
applications = [
{
id: "3242342ffww3423",
applicationName: "Facebook",
platform: "android",
category: "Business",
status: "Published"
},
{
icon: "http://dl1.cbsistatic.com/i/r/2016/08/08/0e67e43a-5a45-41ab-b81d-acfba8708044/resize/736x552/0c0ee669677b5060a0fa1bfb0c7873b4/android-logo-promo-470.png",
id: "324234233423423",
applicationName: "Twitter",
platform: "android",
category: "Business",
status: "Created"
},
{
icon: "https://www.greenfoot.org/images/logos/macos.png",
id: "3242d3423423423",
applicationName: "Massenger",
platform: "android",
category: "Business",
status: "In Review"
},
];
componentWillMount() { componentWillMount() {
/** /**
*Loading the theme files based on the the user-preference. *Loading the theme files based on the the user-preference.
*/ */
Theme.insertThemingScripts(this.scriptId); Theme.insertThemingScripts(this.scriptId);
}
componentWillUnmount() {
Theme.removeThemingScripts(this.scriptId);
// this.setState({data: this.data});
}
componentDidMount() {
let getApps = ApplicationMgtApi.getApplications(); let getApps = ApplicationMgtApi.getApplications();
getApps.then(response => { getApps.then(response => {
let apps = this.setData(response.data.applications); let apps = this.setData(response.data.applications);
@ -108,6 +137,15 @@ class ApplicationListing extends Component {
}); });
} }
componentWillUnmount() {
Theme.removeThemingScripts(this.scriptId);
// this.setState({data: this.data});
}
componentDidMount() {
}
/** /**
* Extract application from application list and update the state. * Extract application from application list and update the state.
* */ * */
@ -165,32 +203,80 @@ class ApplicationListing extends Component {
return 0; return 0;
} }
onRowClick(id) { onRowClick() {
console.log("sfsdfsdf");
let style = {
width: '250px',
marginLeft: '250px'
};
let appListStyle = {
marginRight: '250px',
}
this.setState({drawer: style, appListStyle: appListStyle});
//TODO: Remove console logs. //TODO: Remove console logs.
ApplicationMgtApi.getApplication(id).then(response => { // ApplicationMgtApi.getApplication(id).then(response => {
console.log(response); // console.log(response);
}).catch(err => { // this.setState({open: true, application:response.data})
console.log(err) // }).catch(err => {
}); // console.log(err)
// });
// this.props.history.push("apps/" + id); // this.props.history.push("apps/" + id);
} }
handleButtonClick(id) {
console.log("Application Listing", id);
this.props.history.push("apps/" + id);
}
render() { render() {
return ( return (
<div className="middle applicationListingMiddle">
<Card className="applicationListingCard"> <div id="application-list" style={this.state.appListStyle}>
<TextField <Table striped hover>
hintText="Search" <thead>
className="applicationListingSearch" <tr>
onChange={this.searchApplications}/> <th></th>
<CardTitle title="Applications" className="applicationListTitle"/> {/* TODO: Remove console.log and add sort method. */}
<DataTable <th onClick={() => {console.log("sort")}}>Application Name</th>
headers={this.headers} <th>Category</th>
data={this.state.searchedApplications} <th>Platform</th>
handleRowClick={this.onRowClick} <th>Status</th>
noDataMessage={{type: 'button', text: 'Create Application'}} <th></th>
/> </tr>
</Card> </thead>
<tbody>
{this.applications.map(
(application) => {
return (
<tr key={application.id} onClick={this.onRowClick}>
<td>
{/* TODO: Move this styles to css. */}
<img
src={application.icon}
height='50px'
width='50px'
style={{border: 'solid 1px black', borderRadius: "100%"}}
/></td>
<td>{application.applicationName}</td>
<td>{application.category}</td>
<td>{application.platform}</td>
<td>{application.status}</td>
<td><i>Edit</i></td>
</tr>
)
}
)}
</tbody>
</Table>
<Drawer style={this.state.drawer}>
<div id="application-view">
</div>
</Drawer>
</div> </div>
); );
} }

@ -18,13 +18,54 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import {withRouter} from 'react-router-dom'; import {withRouter} from 'react-router-dom';
import IconButton from 'material-ui/IconButton'
import Create from 'material-ui/svg-icons/content/create';
/** /**
* Application view component. * Application view component.
* Shows the details of the application. * Shows the details of the application.
* */ * */
class ApplicationView extends Component{ class ApplicationView extends Component{
constructor() {
super();
this.state = {
application: {}
}
}
componentWillReceiveProps(props, nextProps) {
this.setState({application: props.application});
console.log(props.application, nextProps)
}
componentDidMount() {
//Download image artifacts.
// this.setState({application: this.props.application});
}
handleEdit() {
this.props.history.push("/assets/apps/edit/" + this.state.application.uuid);
}
render() {
const platform = this.state.application;
console.log(platform);
return (
<div>
<label>Application Name : {this.state.application.name}</label>
<br/>
<label>Description: {this.state.application.description}</label>
<br/>
<IconButton onClick={this.handleEdit.bind(this)}>
<Create/>
</IconButton>
</div>
);
}
} }
export default withRouter(ApplicationView); export default withRouter(ApplicationView);

@ -19,11 +19,9 @@
import Theme from '../../../theme'; import Theme from '../../../theme';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import MenuItem from 'material-ui/MenuItem';
import SelectField from 'material-ui/SelectField';
import AuthHandler from "../../../api/authHandler"; import AuthHandler from "../../../api/authHandler";
import RaisedButton from 'material-ui/RaisedButton';
import PlatformMgtApi from "../../../api/platformMgtApi"; import PlatformMgtApi from "../../../api/platformMgtApi";
import {FormGroup, Input, Label} from 'reactstrap';
/** /**
* The first step of the application creation wizard. * The first step of the application creation wizard.
@ -42,6 +40,8 @@ class Step1 extends Component {
constructor() { constructor() {
super(); super();
this.setPlatforms = this.setPlatforms.bind(this); this.setPlatforms = this.setPlatforms.bind(this);
this.setStepData = this.setStepData.bind(this);
this.cancel = this.cancel.bind(this);
this.platforms = []; this.platforms = [];
this.state = { this.state = {
finished: false, finished: false,
@ -61,12 +61,13 @@ class Step1 extends Component {
/** /**
*Loading the theme files based on the the user-preference. *Loading the theme files based on the the user-preference.
*/ */
Theme.insertThemingScripts(this.scriptId); Theme.insertThemingScripts(this.scriptId);
} }
componentWillUnmount() { componentWillUnmount() {
Theme.removeThemingScripts(this.scriptId); Theme.removeThemingScripts(this.scriptId);
} }
componentDidMount() { componentDidMount() {
//Get the list of available platforms and set to the state. //Get the list of available platforms and set to the state.
PlatformMgtApi.getPlatforms().then(response => { PlatformMgtApi.getPlatforms().then(response => {
@ -88,14 +89,14 @@ class Step1 extends Component {
platform = platforms[index]; platform = platforms[index];
tmpPlatforms.push(platform); tmpPlatforms.push(platform);
} }
this.setState({platforms: tmpPlatforms, platformSelectedIndex: 0, platform: tmpPlatforms[0].identifier}) this.setState({platforms: tmpPlatforms, platformSelectedIndex: 0, platform: tmpPlatforms[0].name})
} }
/** /**
* Persist the current form data to the state. * Persist the current form data to the state.
* */ * */
setStepData() { setStepData() {
console.log("Platforms",this.state.platforms); console.log("Platforms", this.state.platforms);
let step = { let step = {
store: this.state.store, store: this.state.store,
platform: this.state.platforms[this.state.platformSelectedIndex] platform: this.state.platforms[this.state.platformSelectedIndex]
@ -104,77 +105,54 @@ class Step1 extends Component {
this.props.setData("step1", {step: step}); this.props.setData("step1", {step: step});
} }
/** cancel() {
* Handles Next button click.
* Validates the form.
* Sets the data to the state.
* Invokes the handleNext method of Create component.
* */
handleClick() {
this.setStepData();
} }
/** /**
* Triggers when changing the Platform selection. * Triggers when changing the Platform selection.
* */ * */
onChangePlatform(event, index, value) { onChangePlatform(event) {
console.log(this.state.platforms[index]); console.log(event.target.value, this.state.platforms);
this.setState({platform: this.state.platforms[index].identifier, platformSelectedIndex: index}); let id = event.target.value;
let selectedPlatform = this.state.platforms.filter((platform) => {
return platform.identifier === id;
});
console.log(selectedPlatform);
this.setState({platform: selectedPlatform});
}; };
/** /**
* Triggers when changing the Store selection. * Triggers when changing the Store selection.
* */ * */
onChangeStore(event, index, value) { onChangeStore(event) {
this.setState({store: value}); console.log(event.target.value);
this.setState({store: event.target.value});
}; };
render() { render() {
return ( return (
<div> <div>
<div className="creatediv">
<div> <FormGroup>
<div> <Label for="store">Store Type</Label>
<SelectField <Input type="select" name="store" id="store" className="input-custom"
floatingLabelText="Store Type*" onChange={this.onChangeStore.bind(this)}>
value={this.state.store} <option>Enterprise</option>
floatingLabelFixed={true} <option>Public</option>
onChange={this.onChangeStore.bind(this)} </Input>
> </FormGroup>
<MenuItem value={0} primaryText="Enterprise"/> <FormGroup>
<MenuItem value={1} primaryText="Public"/> <Label for="store">Platform</Label>
</SelectField> <Input type="select" name="store" id="store" onChange={this.onChangePlatform.bind(this)}>
<br/> {this.state.platforms.length > 0 ? this.state.platforms.map(platform => {
<SelectField return (
floatingLabelText="Platform*" <option value={platform.identifier}>{platform.name}</option>
value={this.state.platform} )
floatingLabelFixed={true} }) : <option>No Platforms</option>}
onChange={this.onChangePlatform.bind(this)} </Input>
> </FormGroup>
{this.state.platforms.length > 0 ? this.state.platforms.map(platform => {
return (
<MenuItem
key={Math.random()}
value={platform.identifier}
primaryText={platform.name}
/>
)
}) : <div/>}
</SelectField>
</div>
<br/>
<br/>
<div className="nextButton">
<RaisedButton
label="Next >"
primary={true}
onClick={this.handleClick.bind(this)}
/>
</div>
</div>
</div>
</div> </div>
); );
} }

@ -18,17 +18,10 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Theme from '../../../theme'; import Theme from '../../../theme';
import Chip from 'material-ui/Chip';
import Dropzone from 'react-dropzone';
import React, {Component} from 'react'; import React, {Component} from 'react';
import MenuItem from 'material-ui/MenuItem'; 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 SelectField from 'material-ui/SelectField';
import RaisedButton from 'material-ui/RaisedButton'; import {Badge, FormGroup, Input, Label} from 'reactstrap';
import Clear from 'material-ui/svg-icons/content/clear';
import {GridList, GridTile} from 'material-ui/GridList';
/** /**
* The Second step of application create wizard. * The Second step of application create wizard.
@ -40,9 +33,6 @@ import {GridList, GridTile} from 'material-ui/GridList';
* * Application Tags : {Used Material UI Chip component} * * Application Tags : {Used Material UI Chip component}
* * Application Category. * * Application Category.
* * Platform Specific properties. * * Platform Specific properties.
* * Screenshots
* * Banner
* * Icon
* *
* Parent Component: Create * Parent Component: Create
* Props: * Props:
@ -130,27 +120,14 @@ class Step2 extends Component {
* Handles Chip delete function. * Handles Chip delete function.
* Removes the tag from state.tags * Removes the tag from state.tags
* */ * */
handleRequestDelete(key) { handleRequestDelete(event) {
this.chipData = this.state.tags; this.chipData = this.state.tags;
const chipToDelete = this.chipData.map((chip) => chip.key).indexOf(key); console.log(event.target);
const chipToDelete = this.chipData.map((chip) => chip.value).indexOf(event.target.value);
this.chipData.splice(chipToDelete, 1); this.chipData.splice(chipToDelete, 1);
this.setState({tags: this.chipData}); this.setState({tags: this.chipData});
}; };
/**
* Creates Chip array from state.tags.
* */
renderChip(data) {
return (
<Chip
key={data.key}
onRequestDelete={() => this.handleRequestDelete(data.key)}
className="applicationCreateChip">
{data.value}
</Chip>
);
}
onVisibilitySelect(event, index, value) { onVisibilitySelect(event, index, value) {
console.log(value); console.log(value);
let comp = <SelectField> <MenuItem value={0} primaryText="Public"/> let comp = <SelectField> <MenuItem value={0} primaryText="Public"/>
@ -251,15 +228,10 @@ class Step2 extends Component {
* */ * */
setStepData() { setStepData() {
let stepData = { let stepData = {
icon: this.state.icon, // name: this.state.name,
name: this.state.name, // tags: this.state.tags,
tags: this.state.tags, // category: this.categories[this.state.category],
banner: this.state.banner, // description: this.state.description
category: this.categories[this.state.category],
identifier: this.state.identifier,
screenshots: this.state.screenshots,
description: this.state.description,
shortDescription: this.state.shortDescription
}; };
this.props.setData("step2", {step: stepData}); this.props.setData("step2", {step: stepData});
@ -290,216 +262,76 @@ class Step2 extends Component {
} }
}; };
/**
* 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() { render() {
console.log(this.state.visibilityComponent); console.log(this.state.visibilityComponent);
return ( return (
<div className="createStep2Content"> <div className="createStep2Content">
<div> <div>
<div> <div>
<TextField <FormGroup>
id="name" <Label for="app-title">Title*</Label>
hintText="Enter a name for your application." <Input
errorText={this.state.errors["Title"]} required type="text"
floatingLabelText="Name*" name="appName"
floatingLabelFixed={true} id="app-title"
onChange={this.onTextFieldChange.bind(this)} />
/> </FormGroup>
<br/> <FormGroup>
<TextField <Label for="app-description">Description*</Label>
id="identifier" <Input
hintText="Unique Identifier for Application." required type="textarea"
errorText={this.state.errors["Identifier"]} name="appDescription"
floatingLabelText="Identifier*" id="app-description"
floatingLabelFixed={true} />
onChange={this.onTextFieldChange.bind(this)} </FormGroup>
/> <FormGroup>
<br/> <Label for="app-category">Category</Label>
<TextField <Input
id="shortDescription" type="select"
hintText="Enter a short description for your application." name="category"
errorText={this.state.errors["Short Description"]} id="app-category"
floatingLabelText="Short Description*" >
floatingLabelFixed={true} <option>Business</option>
multiLine={true} </Input>
rows={2} </FormGroup>
onChange={this.onTextFieldChange.bind(this)} <FormGroup>
/> <Label for="app-visibility">Visibility</Label>
<br/> <Input
<TextField type="select"
id="description" name="visibility"
errorText={this.state.errors["Description"]} id="app-visibility"
hintText="Enter the description." >
floatingLabelText="Description*" <option>Devices</option>
floatingLabelFixed={true} <option>Roles</option>
multiLine={true} <option>Groups</option>
rows={4} </Input>
onChange={this.onTextFieldChange.bind(this)} </FormGroup>
/> <FormGroup>
<br/> <Label for="app-tags">Tags*</Label>
<SelectField <Input
floatingLabelText="Visibility*" required
value={this.state.visibility} type="text"
floatingLabelFixed={true} value={this.state.defValue}
onChange={this.onVisibilitySelect.bind(this)} name="app-tags"
> id="app-tags"
<MenuItem value={0} primaryText="Public"/> onChange={this.handleTagChange.bind(this)}
<MenuItem value={1} primaryText="Roles"/> onKeyPress={this.addTags.bind(this)}
<MenuItem value={2} primaryText="Devices"/> />
</SelectField> <div id="batch-content">
<br/> {this.state.tags.map(tag => {
<TextField return (
id="tags" <Badge
errorText={this.state.errors["tags"]} style={{margin: '0 2px 0 2px'}}
hintText="Enter Application tags.." value={tag.value}
floatingLabelText="Tags*" onClick={this.handleRequestDelete.bind(this)}
floatingLabelFixed={true} >
value={this.state.defValue} {tag.value}
onChange={this.handleTagChange.bind(this)} </Badge>
onKeyPress={this.addTags.bind(this)} )
/> }
<br/> )}
<div className="applicationCreateWrapper"> </div>
{this.state.tags.map(this.renderChip, this)} </FormGroup>
</div>
<br/>
<SelectField
floatingLabelText="Category*"
value={this.state.category}
floatingLabelFixed={true}
>
<MenuItem value={0} primaryText="Business"/>
</SelectField>
<br/>
{/*Platform Specific Properties.*/}
<div className="platformSpecificPropertyDiv">
<p className="platformSpecificPropertyP">Platform Specific Properties</p>
</div>
<br/>
<div>
<p className="applicationCreateBannerError">{this.state.errors["Banner"]}</p>
<p className="applicationCreateBannerTitle">Banner*:</p>
<GridList className="applicationCreateGrid" 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
className="applicationCreateBannerDropZone"
accept="image/jpeg, image/png"
onDrop={(banner, rejected) => {
this.setState({banner, rejected});
}}
>
<p className="applicationCreateBannerp">+</p>
</Dropzone> : <div/>
}
</GridList>
</div>
<br/>
<div>
<p className="applicationCreateScreenshotError">{this.state.errors["Screenshots"]}</p>
<p className="applicationCreateScreenshotTitle">Screenshots*:</p>
<GridList className="applicationCreateScreenshotGrid" 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
className="applicationCreateScreenshotDropZone"
accept="image/jpeg, image/png"
onDrop={(screenshots, rejected) => {
let tmpScreenshots = this.state.screenshots;
tmpScreenshots.push(screenshots);
this.setState({
screenshots: tmpScreenshots
});
}}
>
<p className="applicationCreateScreenshotp">+</p>
</Dropzone> : <div/>}
</GridList>
</div>
<br/>
<div>
<p className="applcationCreateIconError">{this.state.errors["Icon"]}</p>
<p className="applicationCreateIconTitle">Icon*:</p>
<GridList className="applicationCreateIconGrid" 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
className="applicationCreateIconDropZone"
accept="image/jpeg, image/png"
onDrop={(icon, rejected) => {
this.setState({icon, rejected});
}}
>
<p className="applicationCreateIconp">+</p>
</Dropzone> : <div/>}
</GridList>
</div>
<br/>
</div>
<br/>
<br/>
<div className="applicationCreateBackAndNext">
<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> </div>
</div> </div>

@ -17,33 +17,25 @@
*/ */
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Theme from '../../../theme';
import Chip from 'material-ui/Chip';
import Dropzone from 'react-dropzone';
import React, {Component} from 'react'; import React, {Component} from 'react';
import Toggle from 'material-ui/Toggle';
import MenuItem from 'material-ui/MenuItem'; 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 SelectField from 'material-ui/SelectField';
import RaisedButton from 'material-ui/RaisedButton'; import {FormGroup, Label} from 'reactstrap';
import Theme from '../../../theme';
/** /**
* The Third step of application create wizard. {Application Release Step} * The Third step of application create wizard.
* This step is not compulsory. * This contains following components.
* * * Screenshots
* When click finish, user will prompt to confirm the application creation. * * Banner
* User can go ahead and create the app or cancel. * * Icon
*
* This contains following components:
* * Toggle to select application release. Un-hides the Application Release form.
*
* Application Release Form.
* * Release Channel
* * Application Version
* * Upload component for application.
* *
* Parent Component: Create * Parent Component: Create
* Props: * Props:
* * handleFinish : {type: function, Invokes handleNext function in Parent.} * * handleNext : {type: function, Invokes handleNext function in Parent.}
* * handlePrev : {type: function, Invokes handlePrev function in Parent} * * handlePrev : {type: function, Invokes handlePrev function in Parent}
* * setData : {type: function, Invokes setStepData function in Parent} * * setData : {type: function, Invokes setStepData function in Parent}
* * removeData : {type: Invokes removeStepData function in Parent} * * removeData : {type: Invokes removeStepData function in Parent}
@ -51,16 +43,21 @@ import Theme from '../../../theme';
class Step3 extends Component { class Step3 extends Component {
constructor() { constructor() {
super(); super();
this.handleToggle = this.handleToggle.bind(this);
this.handlePrev = this.handlePrev.bind(this);
this.handleToggle = this.handleToggle.bind(this);
this.handleFinish = this.handleFinish.bind(this);
this.state = { this.state = {
showForm: false, tags: [],
releaseChannel: 1, icon: [],
errors: {} title: "",
errors: {},
banner: [],
defValue: "",
category: 0,
visibility: 0,
description: "",
screenshots: [],
identifier: "",
shortDescription: ""
}; };
this.scriptId = "application-create-step3"; this.scriptId = "application-create-step2";
} }
componentWillMount() { componentWillMount() {
@ -75,71 +72,328 @@ class Step3 extends Component {
} }
/** /**
* Handles finish button click. * Create a tag on Enter key press and set it to the state.
* This invokes handleNext function in parent component. * 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: ""}, console.log(tags));
}
}
/**
* 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.
* */ * */
handleFinish() { handleNext() {
this.props.handleFinish(); 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: "Identifier", value: this.state.identifier},
{name: "Icon", value: this.state.icon}];
this.validate(fields);
} }
/** /**
* Invokes Prev button click. * Invokes the handlePrev function in Create component.
* */ * */
handlePrev() { handlePrev() {
this.props.handlePrev(); this.props.handlePrev();
} }
/** /**
* Handles release application selection. * Handles Chip delete function.
* Removes the tag from state.tags
* */
handleRequestDelete(event) {
this.chipData = this.state.tags;
console.log(event.target);
const chipToDelete = this.chipData.map((chip) => chip.value).indexOf(event.target.value);
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)}
className="applicationCreateChip">
{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.
* */ * */
handleToggle() { validate(fields) {
let hide = this.state.showForm; let errors = {};
this.setState({showForm: !hide}); 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 'Identifier': {
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;
}
}
});
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 = {
icon: this.state.icon,
name: this.state.name,
tags: this.state.tags,
banner: this.state.banner,
category: this.categories[this.state.category],
identifier: this.state.identifier,
screenshots: this.state.screenshots,
description: this.state.description,
shortDescription: this.state.shortDescription
};
this.props.setData("step2", {step: stepData});
};
/**
* Set text field values to state.
* */
onTextFieldChange(event, value) {
let field = event.target.id;
switch (field) {
case "name": {
this.setState({name: value});
break;
}
case "shortDescription": {
this.setState({shortDescription: value});
break;
}
case "description": {
this.setState({description: value});
break;
}
case "identifier": {
this.setState({identifier: 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() { render() {
console.log(this.state.visibilityComponent);
return ( return (
<div className="applicationCreateStepMiddle"> <div className="createStep2Content">
<div> <div>
<Toggle <div>
label="Release the Application"
labelPosition="right"
onToggle={this.handleToggle}
defaultToggled={this.state.showForm}
/>
{/*If toggle is true, the release form will be shown.*/}
{!this.state.showForm ? <div/> :
<div> <div>
<SelectField <FormGroup>
floatingLabelText="Select Release Channel*" <Label for="app-screenshots">Screenshots*</Label>
value={this.state.releaseChannel} <span className="image-sub-title"> (600 X 800 32 bit PNG)</span>
floatingLabelFixed={true} <div id="screenshot-container">
> {this.state.screenshots.map((tile) => (
<MenuItem value={1} primaryText="Alpha"/> <button id="img-btn-screenshot" style={{height: '210px', width: '410px'}}
<MenuItem value={2} primaryText="Beta"/> onMouseEnter={() => {
<MenuItem value={3} primaryText="GA"/> console.log("Mouse Entered")
</SelectField> }}>
<br/> {console.log(tile[0].preview)}
<TextField <img style={{height: '200px', width: '400px'}} src={tile[0].preview}/>
hintText="1.0.0" </button>
floatingLabelText="Version*" ))}
errorText={this.state.errors["title"]} {this.state.screenshots.length < 3 ?
floatingLabelFixed={true} <Dropzone
/><br/> className="applicationCreateScreenshotDropZone"
</div>} accept="image/jpeg, image/png"
<div className="applicationCreateBackAndFinish"> onDrop={(screenshots, rejected) => {
<FlatButton let tmpScreenshots = this.state.screenshots;
label="< Back" tmpScreenshots.push(screenshots);
disabled={false} console.log(screenshots);
onClick={this.handlePrev} this.setState({
className="applicationCreateFinish" screenshots: tmpScreenshots
/> });
<RaisedButton }}
label="Finish" >
primary={true} <p className="applicationCreateScreenshotp">+</p>
onClick={this.handleFinish} </Dropzone> : <div/>}
/> </div>
</FormGroup>
</div>
<div style={{display: 'flex'}}>
<div style={{float: 'left', marginRight: '15px'}}>
<FormGroup>
<Label for="app-icon">Icon*</Label>
<span className="image-sub-title"> (512 X 512 32 bit PNG)</span>
<div id="app-icon-container">
{this.state.icon.map((tile) => (
<button onMouseEnter={() => {
console.log("Mouse Entered")
}}>
<img style={{height: '200px', width: '200px'}} src={tile.preview}/>
</button>
))}
</div>
{this.state.icon.length === 0 ?
<Dropzone
className="applicationCreateIconDropZone"
accept="image/jpeg, image/png"
onDrop={(icon, rejected) => {
this.setState({icon, rejected});
}}
>
<p className="applicationCreateIconp">+</p>
</Dropzone> : <div/>}
</FormGroup>
</div>
<div style={{marginLeft: '15px'}}>
<FormGroup>
<Label for="app-banner">Banner*</Label>
<span className="image-sub-title"> (1000 X 400 32 bit PNG)</span>
<div id="app-banner-container">
{this.state.banner.map((tile) => (
<button onMouseEnter={() => {
console.log("Mouse Entered")
}}>
<img style={{height: '200px', width: '400px'}} src={tile.preview}/>
</button>
))}
{this.state.banner.length === 0 ?
<Dropzone
className="applicationCreateBannerDropZone"
accept="image/jpeg, image/png"
onDrop={(banner, rejected) => {
this.setState({banner, rejected});
}}
>
<p className="applicationCreateBannerp">+</p>
</Dropzone> : <div/>
}
</div>
</FormGroup>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -147,8 +401,8 @@ class Step3 extends Component {
} }
} }
Step3.propTypes = { Step3.prototypes = {
handleFinish: PropTypes.func, handleNext: PropTypes.func,
handlePrev: PropTypes.func, handlePrev: PropTypes.func,
setData: PropTypes.func, setData: PropTypes.func,
removeData: PropTypes.func removeData: PropTypes.func

@ -0,0 +1,158 @@
/*
* 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 React, {Component} from 'react';
import Toggle from 'material-ui/Toggle';
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';
import Theme from '../../../theme';
import {Button, Form, FormGroup, Label, Input, FormText, Badge, Collapse} from 'reactstrap';
import Switch from '../../UIComponents/Switch/Switch'
/**
* The Third step of application create wizard. {Application Release Step}
* This step is not compulsory.
*
* When click finish, user will prompt to confirm the application creation.
* User can go ahead and create the app or cancel.
*
* This contains following components:
* * Toggle to select application release. Un-hides the Application Release form.
*
* Application Release Form.
* * Release Channel
* * Application Version
* * Upload component for application.
*
* Parent Component: Create
* Props:
* * handleFinish : {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 Step4 extends Component {
constructor() {
super();
this.handleToggle = this.handleToggle.bind(this);
this.handlePrev = this.handlePrev.bind(this);
this.handleToggle = this.handleToggle.bind(this);
this.handleFinish = this.handleFinish.bind(this);
this.state = {
showForm: false,
releaseChannel: 1,
errors: {}
};
this.scriptId = "application-create-step3";
}
componentWillMount() {
/**
*Loading the theme files based on the the user-preference.
*/
Theme.insertThemingScripts(this.scriptId);
}
componentWillUnmount() {
Theme.removeThemingScripts(this.scriptId);
}
/**
* Handles finish button click.
* This invokes handleNext function in parent component.
* */
handleFinish() {
this.props.handleFinish();
}
/**
* Invokes Prev button click.
* */
handlePrev() {
this.props.handlePrev();
}
/**
* Handles release application selection.
* */
handleToggle() {
let hide = this.state.showForm;
this.setState({showForm: !hide});
}
render() {
return (
<div className="applicationCreateStepMiddle">
<div>
<FormGroup>
<div id="app-release-switch-content">
<div id="app-release-switch-label">
<Label for="app-release-switch"><strong>Add Release to Application</strong></Label>
</div>
<div id="app-release-switch-switch">
<Switch id="app-release-switch" onChange={this.handleToggle.bind(this)}/>
</div>
</div>
</FormGroup>
<br/>
<div>
<span style={{color: '#BBBBBB', width: '100%', justify: 'left'}}>
<i>Info: </i>
Enabling this will create a release for the current Application.
To upload the Application, please visit to the Release management section of
Application Edit View.
</span>
</div>
{/*If toggle is true, the release form will be shown.*/}
<Collapse isOpen={this.state.showForm}>
<FormGroup>
<Label for="release-channel">Release Channel</Label>
<Input id="input-custom" type="select" mid="release-channel" style={{
width: '200px',
border: 'none',
borderRadius: '0',
borderBottom: 'solid 1px #BDBDBD'
}}>
<option>GA</option>
<option>Alpha</option>
<option>Beta</option>
</Input>
</FormGroup>
<FormGroup>
<Label for="version">Version*</Label>
<Input type="text" id="version input-custom" placeholder="v1.0" required/>
</FormGroup>
</Collapse>
</div>
</div>
);
}
}
Step4.propTypes = {
handleFinish: PropTypes.func,
handlePrev: PropTypes.func,
setData: PropTypes.func,
removeData: PropTypes.func
};
export default Step4;

@ -19,5 +19,6 @@
import Step1 from './Step1'; import Step1 from './Step1';
import Step2 from './Step2'; import Step2 from './Step2';
import Step3 from './Step3'; import Step3 from './Step3';
import Step4 from './Step4';
export {Step1, Step2, Step3}; export {Step1, Step2, Step3, Step4};

@ -0,0 +1,37 @@
/*
* 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 React, {Component} from 'react';
class ApplicationEdit extends Component {
constructor() {
super();
}
render() {
return(
<div id="application-edit-base">
</div>
)
}
}
export default ApplicationEdit;

@ -0,0 +1,44 @@
/*
* 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 React, {Component} from 'react';
class GeneralInfo extends Component {
constructor() {
super();
}
render() {
return(
<div>
</div>
)
}
}
export default GeneralInfo;

@ -0,0 +1,37 @@
/*
* 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 React, {Component} from 'react';
class PackageManager extends Component {
constructor() {
super();
}
render() {
return(
<div>
</div>
)
}
}
export default PackageManager;

@ -0,0 +1,37 @@
/*
* 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 React, {Component} from 'react';
class ReleaseManager extends Component {
constructor() {
super();
}
render() {
return(
<div>
</div>
)
}
}
export default ReleaseManager;

@ -16,25 +16,15 @@
* under the License. * under the License.
*/ */
import Theme from '../../theme';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Badge from 'material-ui/Badge';
import React, {Component} from 'react'; import React, {Component} from 'react';
import AppBar from 'material-ui/AppBar';
import Drawer from 'material-ui/Drawer';
import IconMenu from 'material-ui/IconMenu';
import MenuItem from 'material-ui/MenuItem';
import {withRouter} from 'react-router-dom'; import {withRouter} from 'react-router-dom';
import AuthHandler from "../../api/authHandler"; import AuthHandler from "../../api/authHandler";
import FlatButton from 'material-ui/FlatButton'; import '../../css/font-wso2.css';
import IconButton from 'material-ui/IconButton';
import {List, ListItem} from 'material-ui/List';
import Apps from 'material-ui/svg-icons/navigation/apps';
import Add from 'material-ui/svg-icons/content/add-circle';
import Feedback from 'material-ui/svg-icons/action/feedback';
import DevicesOther from 'material-ui/svg-icons/hardware/devices-other';
import NotificationsIcon from 'material-ui/svg-icons/social/notifications'; import NotificationsIcon from 'material-ui/svg-icons/social/notifications';
import ActionAccountCircle from 'material-ui/svg-icons/action/account-circle'; import ActionAccountCircle from 'material-ui/svg-icons/action/account-circle';
import ApplicationCreate from '../Application/ApplicationCreate';
import {Button, Input, InputGroup,} from 'reactstrap';
/** /**
@ -49,45 +39,21 @@ class BaseLayout extends Component {
super(); super();
this.state = { this.state = {
notifications: 0, notifications: 0,
user: 'Admin' user: 'Admin',
openModal: false
}; };
this.scriptId = "basic-layout"; this.scriptId = "basic-layout";
this.logout = this.logout.bind(this); this.logout = this.logout.bind(this);
} }
componentWillMount() {
/**
*Loading the theme files based on the the user-preference.
*/
Theme.insertThemingScripts(this.scriptId);
}
componentWillUnmount() {
Theme.removeThemingScripts(this.scriptId)
}
handleApplicationClick() { handleApplicationClick() {
this.handleHistory('/assets/apps'); this.handleHistory('/assets/apps');
} }
handleOverviewClick() { handleApplicationCreateClick(event) {
this.handleHistory('/overview'); event.preventDefault();
} event.stopPropagation();
this.setState({openModal: true});
handleApplicationCreateClick() {
this.handleHistory('/assets/apps/create');
}
handlePlatformClick() {
this.handleHistory('/assets/platforms');
}
handlePlatformCreateClick() {
this.handleHistory('/assets/platforms/create');
}
handleReviewClick() {
this.handleHistory('/assets/reviews');
} }
/** /**
@ -104,84 +70,44 @@ class BaseLayout extends Component {
render() { render() {
return ( return (
<div id="container">
<div> <div id="header-content">
<AppBar <div id="header">
title="App Publisher" <span id="header-text">
iconElementRight={ WSO2 IoT App Publisher
<div> </span>
<Badge <div id="header-btn">
badgeContent={this.state.notifications} <Button id="btn"><NotificationsIcon/></Button>
secondary={true} <Button id="btn"><ActionAccountCircle/></Button>
badgeStyle={{top: 12, right: 12}}
>
<IconButton tooltip="Notifications">
<NotificationsIcon/>
</IconButton>
</Badge>
<IconMenu
iconButtonElement={<FlatButton
icon={<ActionAccountCircle/>}
label="sdfdsf"
/>}
anchorOrigin={{horizontal: 'left', vertical: 'top'}}
targetOrigin={{horizontal: 'left', vertical: 'top'}}
onChange={this.logout}
>
<MenuItem value={0} primaryText="Logout" />
</IconMenu>
{/*<FlatButton*/}
{/*icon={<ActionAccountCircle/>}*/}
{/*onClick={() => {console.log("Clicked")}}*/}
{/*label={this.props.user.getUserName()}*/}
{/*/>*/}
</div> </div>
} </div>
/> <div id="search-box">
<div> <InputGroup>
<Drawer containerStyle={{height: 'calc(100% - 64px)', width: '15%', top: '10%'}} open={true}> <Input id="search"
<List> name="search"
<ListItem placeholder={'Search for Applications'}
primaryText="Applications" onChange={(event) => console.log(event.target.value)}
leftIcon={<Apps/>}
initiallyOpen={false}
primaryTogglesNestedList={true}
onClick={this.handleApplicationClick.bind(this)}
nestedItems={[
<ListItem
key={1}
primaryText="Create"
onClick={this.handleApplicationCreateClick.bind(this)}
leftIcon={<Add/>}
/>
]}
/> />
<ListItem </InputGroup>
primaryText="Platforms" </div>
leftIcon={<DevicesOther/>}
initiallyOpen={false}
primaryTogglesNestedList={true}
onClick={this.handlePlatformClick.bind(this)}
nestedItems={[
<ListItem
key={1}
primaryText="Create"
onClick={this.handlePlatformCreateClick.bind(this)}
leftIcon={<Add/>}
/>
]}
/>
<ListItem
primaryText="Reviews"
onClick={this.handleReviewClick.bind(this)}
leftIcon={<Feedback/>}
/>
</List>
</Drawer>
</div> </div>
<div className="basicLayoutDiv"> <div id="add-btn-container">
<Button id="add-btn"
onClick={this.handleApplicationCreateClick.bind(this)}
>
<h3>
<strong>+</strong>
</h3>
</Button>
</div>
<div className="application-content"
style={this.state.style}
>
{this.props.children} {this.props.children}
</div> </div>
<ApplicationCreate
open={this.state.openModal}
/>
</div> </div>
); );
} }

@ -0,0 +1,35 @@
/*
* 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 React, {Component} from 'react';
import './chip.css';
class Chip extends Component {
render() {
return (
<div className="chip">
{this.props.image?<img src={this.props.image} alt="Person" width="96" height="96" />:<div/>}
{this.props.text}
<span className="close-btn" >&times;</span>
</div>
)
}
}
export default Chip;

@ -0,0 +1,48 @@
/*
* 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.
*/
.chip {
display: inline-block;
padding: 0 25px;
height: 50px;
font-size: 16px;
line-height: 50px;
border-radius: 25px;
background-color: #f1f1f1;
}
.chip img {
float: left;
margin: 0 10px 0 -25px;
height: 50px;
width: 50px;
border-radius: 50%;
}
.close-btn {
padding-left: 10px;
color: #888;
font-weight: bold;
float: right;
font-size: 20px;
cursor: pointer;
}
.close-btn:hover {
color: #000;
}

@ -54,6 +54,7 @@ class DataTable extends Component {
constructor() { constructor() {
super(); super();
this.handleRowClick = this.handleRowClick.bind(this); this.handleRowClick = this.handleRowClick.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
this.state = { this.state = {
data: [], data: [],
headers: [], headers: [],
@ -75,6 +76,10 @@ class DataTable extends Component {
} }
shouldComponentUpdate(nextProps, nextState) { shouldComponentUpdate(nextProps, nextState) {
if (!nextProps.data) {
this.setState({data: nextState.data});
return true;
}
this.setState({data: nextProps.data}); this.setState({data: nextProps.data});
return true; return true;
} }
@ -87,6 +92,10 @@ class DataTable extends Component {
this.props.handleRowClick(id); this.props.handleRowClick(id);
} }
handleBtnClick(id) {
this.props.handleButtonClick(id);
}
render() { render() {
const {data, headers} = this.state; const {data, headers} = this.state;
@ -121,6 +130,7 @@ class DataTable extends Component {
<DataTableRow <DataTableRow
key={dataItem.id} key={dataItem.id}
dataItem={dataItem} dataItem={dataItem}
handleButtonClick={this.handleBtnClick}
handleClick={this.handleRowClick} handleClick={this.handleRowClick}
/> />
) )

@ -19,7 +19,11 @@
import Theme from '../../theme'; import Theme from '../../theme';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import IconButton from 'material-ui/IconButton';
import Create from 'material-ui/svg-icons/content/create'
import {TableRow, TableRowColumn} from 'material-ui/Table'; import {TableRow, TableRowColumn} from 'material-ui/Table';
import Avatar from 'material-ui/Avatar';
/** /**
* Data table row component. * Data table row component.
@ -51,10 +55,17 @@ class DataTableRow extends Component {
/** /**
* Triggers the click event on the data table row. * Triggers the click event on the data table row.
* */ * */
handleClick() { handleClick(event) {
event.stopPropagation();
this.props.handleClick(this.state.dataItem.id); this.props.handleClick(this.state.dataItem.id);
} }
handleBtnClick(event) {
event.stopPropagation();
console.log(event.target['id'])
this.props.handleButtonClick(event.target['id']);
}
render() { render() {
const {dataItem} = this.state; const {dataItem} = this.state;
return ( return (
@ -62,6 +73,12 @@ class DataTableRow extends Component {
key={this.props.key} key={this.props.key}
onClick={this.handleClick.bind(this)} onClick={this.handleClick.bind(this)}
> >
<TableRowColumn
className="datatableRowColumn"
key={Math.random()}
>
<Avatar>{dataItem.name}</Avatar>
</TableRowColumn>
{Object.keys(dataItem).map((key) => { {Object.keys(dataItem).map((key) => {
if (key !== 'id') { if (key !== 'id') {
return ( return (
@ -71,11 +88,17 @@ class DataTableRow extends Component {
> >
{dataItem[key]} {dataItem[key]}
</TableRowColumn>) </TableRowColumn>)
} else {
return <TableRowColumn key={key}/>
} }
})} })}
<TableRowColumn
className="datatableRowColumn"
key={dataItem.id}
>
<IconButton id={dataItem.id} onClick={this.handleBtnClick.bind(this)}>
<Create id={dataItem.id}/>
</IconButton>
</TableRowColumn>
</TableRow> </TableRow>
); );
} }

@ -0,0 +1,43 @@
/*
* 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 React, {Component} from 'react';
import './drawer.css';
class Drawer extends Component {
render() {
return (
<div>
<div id="mySidenav" className="sidenav" style={this.props.style}>
{this.props.children}
</div>
</div>
);
}
}
Drawer.propTypes = {
style: PropTypes.object,
children: PropTypes.node
};
export default Drawer;

@ -0,0 +1,67 @@
/*
* 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.
*/
.sidenav {
height: 100%; /* 100% Full-height */
width: 0; /* 0 width - change this with JavaScript */
position: fixed; /* Stay in place */
z-index: 1; /* Stay on top */
top: 11%;
right: 0%;
background-color: white;
overflow-x: hidden; /* Disable horizontal scroll */
padding-top: 60px; /* Place content 60px from the top */
transition: 0.5s; /* 0.5 second transition effect to slide in the sidenav */
border: solid 1px black;
}
.sidenav a {
padding: 8px 8px 8px 32px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
transition: 0.3s
}
/* When you mouse over the navigation links, change their color */
.sidenav a:hover, .offcanvas a:focus{
color: #f1f1f1;
}
/* Position and style the close button (top right corner) */
.sidenav .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
/* Style page content - use this if you want to push the page content to the right when you open the side navigation */
#main {
transition: margin-left .5s;
padding: 20px;
}
/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
@media screen and (max-height: 450px) {
.sidenav {padding-top: 15px;}
.sidenav a {font-size: 18px;}
}

@ -0,0 +1,35 @@
/*
* 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 React, {Component} from 'react';
import './switch.css';
class Switch extends Component {
render() {
const {height, width} = this.props;
return (
<label className="switch">
<input type="checkbox" onChange={this.props.onChange}/>
<span className="slider round"></span>
</label>
)
}
}
export default Switch;

@ -0,0 +1,76 @@
/*
* 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.
*/
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 40px;
height: 24px;
}
/* Hide default HTML checkbox */
.switch input {display:none;}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 16px;
width: 16px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(16px);
-ms-transform: translateX(16px);
transform: translateX(16px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}

@ -16,15 +16,10 @@
* under the License. * under the License.
*/ */
import qs from 'qs';
import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import Checkbox from 'material-ui/Checkbox';
import TextField from 'material-ui/TextField';
import {Redirect, Switch} from 'react-router-dom'; import {Redirect, Switch} from 'react-router-dom';
import AuthHandler from '../../../api/authHandler'; import AuthHandler from '../../../api/authHandler';
import RaisedButton from 'material-ui/RaisedButton'; import {Button, Card, CardBlock, CardSubtitle, CardTitle, Col, Form, FormGroup, Input, Label} from 'reactstrap';
import {Card, CardActions, CardTitle} from 'material-ui/Card';
/** /**
* The Login Component. * The Login Component.
@ -72,9 +67,10 @@ class Login extends Component {
* Handles the username field change event. * Handles the username field change event.
* */ * */
onUserNameChange(event, value) { onUserNameChange(event, value) {
console.log(event.target.value);
this.setState( this.setState(
{ {
userName: value userName: event.target.value
} }
); );
} }
@ -85,7 +81,7 @@ class Login extends Component {
onPasswordChange(event, value) { onPasswordChange(event, value) {
this.setState( this.setState(
{ {
password: value password: event.target.value
} }
); );
} }
@ -136,43 +132,32 @@ class Login extends Component {
if (!this.state.isLoggedIn) { if (!this.state.isLoggedIn) {
return ( return (
<div> <div style={{width: '50%', margin: '0 auto'}}>
{/*TODO: Style the components.*/} {/*TODO: Style the components.*/}
<Card id="login-card">
<CardBlock>
<CardTitle>WSO2 IoT APP Publisher</CardTitle>
<Form onSubmit={this.handleLogin.bind(this)}>
<FormGroup row>
<Label for="userName" sm={2}>User Name:</Label>
<Col sm={10}>
<Input type="text" name="userName" id="userName" placeholder="User Name" onChange={this.onUserNameChange.bind(this)}/>
</Col>
<Card> </FormGroup>
<CardTitle title="WSO2 IoT App Publisher"/> <FormGroup row>
<CardActions> <Label for="password" sm={2}>Password:</Label>
<form onSubmit={this.handleLogin.bind(this)}> <Col sm={10}>
<TextField <Input type="password" name="text" id="password" placeholder="Password" onChange={this.onPasswordChange.bind(this)}/>
hintText="Enter the User Name." </Col>
id="username" </FormGroup>
errorText={this.state.errors["userNameError"]} <FormGroup check row>
floatingLabelText="User Name*" <Col sm={{ size: 10, offset: 2 }}>
floatingLabelFixed={true} <Button type="submit" id="login-btn">Submit</Button>
value={this.state.userName} </Col>
onChange={this.onUserNameChange.bind(this)} </FormGroup>
/> </Form>
<br/> </CardBlock>
<TextField
hintText="Enter the Password."
id="password"
type="password"
errorText={this.state.errors["passwordError"]}
floatingLabelText="Password*"
floatingLabelFixed={true}
value={this.state.password}
onChange={this.onPasswordChange.bind(this)}
/>
<br/>
<Checkbox
label="Remember me."
onCheck={this.handleRememberMe.bind(this)}
checked={this.state.rememberMe}
/>
<br/>
<RaisedButton type="submit" label="Login"/>
</form>
</CardActions>
</Card> </Card>
</div>); </div>);
} else { } else {

@ -23,9 +23,10 @@ import PlatformCreate from './Platform/PlatformCreate';
import PlatformListing from './Platform/PlatformListing'; import PlatformListing from './Platform/PlatformListing';
import ApplicationCreate from './Application/ApplicationCreate'; import ApplicationCreate from './Application/ApplicationCreate';
import ApplicationListing from './Application/ApplicationListing'; import ApplicationListing from './Application/ApplicationListing';
import ApplicationEdit from './Application/Edit/ApplicationEditBaseLayout';
/** /**
* Contains all UI components related to Application, Login and Platform * Contains all UI components related to Application, Login and Platform
*/ */
export {Login, BaseLayout, ApplicationCreate, ApplicationListing, PlatformListing, NotFound, PlatformCreate}; export {Login, BaseLayout, ApplicationCreate, ApplicationListing, PlatformListing, NotFound, PlatformCreate, ApplicationEdit};

@ -1,5 +1,186 @@
body { body {
margin: 0; width: 100%;
padding: 0; font-family: sans-serif;
font-family: sans-serif;
} }
#userName {
border-radius: 0;
}
#password {
border-radius: 0;
}
#login-btn {
border-radius: 0;
background-color: navy;
color: white;
cursor: pointer;
}
#login-card {
border-radius: 0;
background-color: #BaBaBa;
}
#container {
background-color: #ffffff;
}
#header-content {
height: 100px;
width: 100%;
background-color: #BDBDBD;
border-bottom: solid 2px;
}
#add-btn {
border-radius: 50%;
border: solid 2px;
position: absolute;
background-color: #BDBDBD;
left: 15px;
top: 75px;
cursor: pointer;
height: 50px;
width: 50px;
}
.add-btn.div {
position: relative;
margin-top: 20px;
margin-left: 20px;
}
#fw-api:before {
content: '\e601';
}
#btn {
background-color: #BDBDBD;
border-color: #BDBDBD;
}
#header-text {
font-size: 25px;
top: 10px;
margin-left: 10px;
}
#header-btn {
float: right;
}
#search-box {
float: right;
}
#search {
background-color: #BDBDBD;
left: 110px;
top: 20px;
height: 25px;
border: hidden;
}
#application-list {
margin-top: 20px;
}
.applicationCreateBannerDropZone {
width: 300px;
height: 150px;
border-radius: 5%;
background-color: rgba(157, 159, 157, 0.53);
border: dashed #888888 2px;
}
.applicationCreateBannerp {
margin: 70px 40px 40px 150px;
}
.applicationCreateScreenshotDropZone {
width: 150px;
height: 150px;
margin: 0 5px 0 5px;
border-radius: 10%;
background-color: rgba(157, 159, 157, 0.53);
border: dashed #888888 2px;
}
.applicationCreateIconDropZone {
width: 150px;
height: 150px;
border-radius: 10%;
background-color: rgba(157, 159, 157, 0.53);
border: dashed #888888 2px;
}
.applicationCreateIconp {
margin: 70px 40px 70px 70px;
}
.applicationCreateScreenshotp {
margin: 70px 40px 70px 70px;
}
#screenshot-container {
display: flex;
overflow-x: auto;
height: 170px;
}
#app-icon-container {
max-width: 200px;
overflow-x: auto;
}
#modal-body-content {
max-height: 700px;
overflow-y: auto;
}
#img-btn-screenshot {
margin: 0 5px 0 5px;
}
#app-create-modal {
max-width: 700px;
overflow-x: auto;
}
#store {
border: none;
border-bottom: solid #BDBDBD 1px;
border-radius: 0px;
width: 200px;
}
#version {
border: none;
border-bottom: solid #BDBDBD 1px;
border-radius: 0px;
width: 200px;
}
#app-release-switch-content {
display: flex;
}
#app-release-switch-label {
position: absolute;
float: left;
}
#app-release-switch-switch {
position: absolute;
right: 10px;
}
.image-sub-title {
font-style: italic;
font-size: 12px;
color: #818181;
}

@ -20,6 +20,8 @@ import './index.css';
import React from 'react'; import React from 'react';
import Publisher from './App'; import Publisher from './App';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css';
import './css/font-wso2.css';
import registerServiceWorker from './registerServiceWorker'; import registerServiceWorker from './registerServiceWorker';
/** /**

@ -16,6 +16,7 @@
* under the License. * under the License.
*/ */
var path = require('path'); var path = require('path');
import '!!style-loader!css-loader!src/css/font-wso2.css';
const config = { const config = {
entry: { entry: {
@ -61,7 +62,7 @@ const config = {
}, },
resolve: { resolve: {
// you can now require('file') instead of require('file.coffee') // you can now require('file') instead of require('file.coffee')
extensions: ['.jsx', '.js'] extensions: ['.jsx', '.js', '.ttf', '.woff', '.woff2', '.svg']
} }
}; };

Loading…
Cancel
Save