Api integration: Application Create steps.

feature/appm-store/pbac
Menaka Jayawardena 7 years ago
parent 4cdb1fc4c9
commit 7fa3c886fb

@ -10,18 +10,18 @@
"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", "bootstrap": "^4.0.0-beta",
"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",
"material-ui": "^0.19.1", "material-ui": "^0.19.3",
"prop-types": "^15.5.10", "prop-types": "^15.6.0",
"qs": "^6.5.0", "qs": "^6.5.1",
"react": "^15.6.1", "react": "^15.6.2",
"react-addons-css-transition-group": "^15.6.0", "react-addons-css-transition-group": "^15.6.2",
"react-addons-transition-group": "^15.6.0", "react-addons-transition-group": "^15.6.2",
"react-dom": "^15.6.1", "react-dom": "^15.6.2",
"react-dropzone": "^4.1.2", "react-dropzone": "^4.1.3",
"react-images-uploader": "^1.1.0", "react-images-uploader": "^1.1.0",
"react-material-ui-form-validator": "^0.5.1", "react-material-ui-form-validator": "^0.5.1",
"react-modal": "^2.3.2", "react-modal": "^2.3.2",
@ -43,8 +43,8 @@
"css-loader": "^0.28.7", "css-loader": "^0.28.7",
"less": "^2.7.2", "less": "^2.7.2",
"less-loader": "^4.0.4", "less-loader": "^4.0.4",
"mocha": "^3.4.1", "mocha": "^3.5.3",
"mock-local-storage": "^1.0.2", "mock-local-storage": "^1.0.5",
"node-sass": "^4.5.3", "node-sass": "^4.5.3",
"react-intl": "^2.4.0", "react-intl": "^2.4.0",
"sass-loader": "^6.0.6", "sass-loader": "^6.0.6",

@ -39,13 +39,16 @@ body {
} }
#login-container { #login-container {
width: 50%;
margin: 0 auto
} }
#login-card { #login-card {
width: 20%;
height: 50%;
margin: 10% auto;
padding: 10px;
border-radius: 0; border-radius: 0;
background-color: #BaBaBa; background-color: #ffffff;
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
} }
/* Base layout container */ /* Base layout container */
@ -130,7 +133,7 @@ body {
float: right; float: right;
top: 75px; top: 75px;
left: 150px; left: 150px;
margin-right: 16px; margin-right: 40px;
} }
#search { #search {
@ -148,14 +151,13 @@ body {
/* Application Add button */ /* Application Add button */
#add-btn-container { #add-btn-container {
position: absolute; position: absolute;
left: 12%; left: 11%;
top: 100px; top: 100px;
} }
#app-main-content { #app-main-content {
height: 100%; margin-top: 140px;
position: inherit; max-width: 98%;
top: 125px;
} }
/* Holds the app publisher pages. */ /* Holds the app publisher pages. */
@ -163,8 +165,8 @@ body {
height: auto; height: auto;
width: 80%; width: 80%;
margin: 20px auto; margin: 20px auto;
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); box-shadow: 2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
padding: 10px 10px 10px 10px; padding: 0 10px 10px 10px;
} }
.stepper-header { .stepper-header {
@ -183,10 +185,17 @@ body {
} }
#application-list { #application-list {
margin-top: 20px;
transition: margin-right .5s; transition: margin-right .5s;
} }
.app-list-table-header {
height: 100px;
}
#app-visibility-default {
display: none;
}
#app-image-screenshot { #app-image-screenshot {
width: 300px; width: 300px;
height: 300px; height: 300px;
@ -207,7 +216,6 @@ body {
height: 150px; height: 150px;
border-radius: 5%; border-radius: 5%;
position: relative; position: relative;
background-color: rgba(157, 159, 157, 0.53);
border: dashed #888888 2px; border: dashed #888888 2px;
} }
@ -223,7 +231,6 @@ body {
margin: 0 5px 0 5px; margin: 0 5px 0 5px;
border-radius: 10%; border-radius: 10%;
position: relative; position: relative;
background-color: rgba(157, 159, 157, 0.53);
border: dashed #888888 2px; border: dashed #888888 2px;
} }
@ -238,7 +245,6 @@ body {
height: 150px; height: 150px;
border-radius: 10%; border-radius: 10%;
position: relative; position: relative;
background-color: rgba(157, 159, 157, 0.53);
border: dashed #888888 2px; border: dashed #888888 2px;
} }
@ -249,6 +255,7 @@ body {
} }
#screenshot-container { #screenshot-container {
max-width: 600px;
display: flex; display: flex;
overflow-x: auto; overflow-x: auto;
height: 200px; height: 200px;
@ -266,12 +273,13 @@ body {
#secondary-button { #secondary-button {
float: right; float: right;
color: #979797;
background-color: transparent; background-color: transparent;
border: none; border: none;
} }
#secondary-button:hover { #secondary-button:hover {
background-color: #e9e9e9; background-color: #d8d8d8;
outline: none; outline: none;
cursor: pointer; cursor: pointer;
} }
@ -327,12 +335,12 @@ body {
} }
/* Application View */ /* Application View */
#application-view-content { #application-view-content {
width: 100%; width: 100%;
} }
#application-view-row { #application-view-row {
margin: 10px 10px 20px 20px; margin: 10px 10px 0 20px;
} }
#app-icon { #app-icon {
@ -366,14 +374,14 @@ body {
} }
/* Application Edit Base Layout */ /* Application Edit Base Layout */
#application-edit-header { #application-edit-header {
height: 50px; height: 40px;
width: 100%; width: 100%;
margin: 0; margin-top: 20px;
font-size: 20px; margin-bottom: 20px;
border-bottom: solid 1px #d8d8d8; font-size: 25px;
} }
.application-header-text { .application-header-text {
margin: 10px 0px 0px 10px; margin: 10px 0px 0px 10px;
} }
@ -399,13 +407,14 @@ body {
} }
/*Tab styling*/ /*Tab styling*/
div.tab { div.tab {
float: left; float: left;
border-right: 1px solid #d8d8d8; border-right: 1px solid #d8d8d8;
height: 100%; height: 100%;
} }
/* Style the tab buttons */ /* Style the tab buttons */
div.tab button { div.tab button {
display: block; display: block;
background-color: inherit; background-color: inherit;
@ -418,24 +427,23 @@ div.tab button {
cursor: pointer; cursor: pointer;
transition: 0.3s; transition: 0.3s;
} }
/* Change background color of buttons on hover */ /* Change background color of buttons on hover */
div.tab button:hover { div.tab button:hover {
background-color: #ddd6d7; background-color: #ddd6d7;
cursor: pointer; cursor: pointer;
} }
/* Create an active/current "tab button" class */ /* Create an active/current "tab button" class */
div.tab button.active { div.tab button.active {
background-color: #1b3bcc; background-color: #1b3bcc;
color: white; color: white;
} }
#application-edit-main-container { #application-edit-main-container {
display: flex; display: flex;
} }
#application-edit-outer-content { #application-edit-outer-content {
height: auto; height: auto;
width: 100%; width: 100%;
@ -453,13 +461,13 @@ div.tab button.active {
.back-to-app { .back-to-app {
position: absolute; position: absolute;
height: 40px; height: 50px;
width: 40px; width: 50px;
border-radius: 50%; border-radius: 50%;
} }
.back-to-app i { .back-to-app i {
padding: 10px 10px 10px 10px; padding: 12px 10px 10px 12px;
} }
.back-to-app:hover { .back-to-app:hover {
@ -469,11 +477,11 @@ div.tab button.active {
} }
/* Create Release and Release management */ /* Create Release and Release management */
.release-header { .release-header {
margin-top: 20px; margin-top: 20px;
margin-bottom: 20px; margin-bottom: 20px;
} }
.release-create { .release-create {
height: 150px; height: 150px;
margin-bottom: 20px; margin-bottom: 20px;
@ -523,12 +531,39 @@ div.tab button.active {
} }
/* Application Edit General Info */ /* Application Edit General Info */
.app-edit-general-info { .app-edit-general-info {
margin-top: 20px; margin-top: 20px;
max-width: 100%; max-width: 100%;
} }
.save-info { .save-info {
float: right; float: right;
margin-bottom: 10px; margin-bottom: 10px;
} }
/* Platform Specific Styles. */
#platform-listing {
margin: 10px;
}
.create-platform {
padding-left: 90%;
}
#platform-list {
margin-top: 20px;
display: flex;
flex-flow: wrap;
}
#platform-content {
width: 200px;
height: 300px;
margin: 10px;
box-shadow: 2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
#platform-content:hover {
background-color: #f2f2f2;
cursor: pointer;
}

@ -76,7 +76,7 @@ class BaseLayout extends Component {
render() { render() {
return ( return (
<Container fluid id="container"> <div>
<div id="header-content"> <div id="header-content">
<div id="header"> <div id="header">
<span id="header-text"> <span id="header-text">
@ -104,10 +104,12 @@ class BaseLayout extends Component {
/> />
</div> </div>
</div> </div>
<Container fluid>
<div id="app-main-content" style={this.state.style}> <div id="app-main-content" style={this.state.style}>
<Row> <Row>
<div className="platform-link-placeholder"> <div className="platform-link-placeholder">
<Button id="secondary-button" onClick={this.onClickPlatforms}><i className="fw fw-settings"></i> Platforms</Button> <Button id="secondary-button" onClick={this.onClickPlatforms}>
<i className="fw fw-settings"></i> Platforms</Button>
</div> </div>
</Row> </Row>
<Row> <Row>
@ -120,8 +122,9 @@ class BaseLayout extends Component {
</div> </div>
</Row> </Row>
</div> </div>
<ApplicationCreate open={this.state.openModal} close={this.closeModal}/>
</Container> </Container>
<ApplicationCreate open={this.state.openModal} close={this.closeModal}/>
</div>
); );
} }
} }

@ -22,6 +22,8 @@ import {Button, Col, Row, Table} from 'reactstrap';
import Drawer from '../UIComponents/Drawer/Drawer'; import Drawer from '../UIComponents/Drawer/Drawer';
import ApplicationView from './View/ApplicationView'; import ApplicationView from './View/ApplicationView';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import ApplicationMgtApi from "../../api/applicationMgtApi";
import AuthHandler from "../../api/authHandler";
/** /**
* The App Create Component. * The App Create Component.
@ -36,10 +38,10 @@ class ApplicationListing extends Component {
super(); super();
this.searchApplications = this.searchApplications.bind(this); this.searchApplications = this.searchApplications.bind(this);
this.onRowClick = this.onRowClick.bind(this); this.onRowClick = this.onRowClick.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.onAppEditClick = this.onAppEditClick.bind(this);
this.getSelectedApplication = this.getSelectedApplication.bind(this);
this.state = { this.state = {
searchedApplications: [], searchedApplications: [],
applications: [], applications: [],
@ -57,7 +59,6 @@ class ApplicationListing extends Component {
}; };
} }
applications = [ applications = [
{ {
id: "3242342ffww3423", id: "3242342ffww3423",
@ -84,35 +85,57 @@ class ApplicationListing extends Component {
}, },
]; ];
componentWillMount() { headers = [
{
// let getApps = ApplicationMgtApi.getApplications(); data_id: "image",
// getApps.then(response => { data_type: "image",
// let apps = this.setData(response.data.applications); sortable: false,
// console.log(apps); //TODO: Remove this. label: ""
// this.setState({searchedApplications: apps}); },
// // console.log(this.setState({data: response.data}), console.log(this.state)); {
// }).catch(err => { data_id: "applicationName",
// AuthHandler.unauthorizedErrorHandler(err); data_type: "string",
// }); sortable: true,
label: "Application Name",
sort: this.sortData
},
{
data_id: "platform",
data_type: "image_array",
sortable: false,
label: "Platform"
},
{
data_id: "category",
data_type: "string",
sortable: false,
label: "Category"
},
{
data_id: "status",
data_type: "string",
sortable: false,
label: "Status"
},
{
data_id: "edit",
data_type: "button",
sortable: false,
label: ""
} }
];
/**
* Extract application from application list and update the state.
* */
setData(applications) {
let apps = [];
for (let app in applications) {
let application = {};
application.id = applications[app].uuid;
application.applicationName = applications[app].name;
application.platform = applications[app].platform.name;
application.category = applications[app].category.id;
application.status = applications[app].currentLifecycle.lifecycleState.name;
apps.push(application);
}
this.setState({searchedApplications: apps}); componentWillMount() {
let getApps = ApplicationMgtApi.getApplications();
getApps.then(response => {
console.log(response.data.applications);
this.setState({searchedApplications: response.data.applications});
// console.log(this.setState({data: response.data}), console.log(this.state));
}).catch(err => {
AuthHandler.unauthorizedErrorHandler(err);
});
} }
/** /**
@ -154,34 +177,22 @@ class ApplicationListing extends Component {
return 0; return 0;
} }
onRowClick() { onRowClick(uuid) {
let selectedApp = this.getSelectedApplication(uuid);
let style = { let style = {
width: '500px', width: '550px',
marginLeft: '500px' marginLeft: '550px'
}; };
let appListStyle = { let appListStyle = {
marginRight: '500px', marginRight: '550px',
}; };
this.setState({drawer: style, appListStyle: appListStyle}); this.setState({drawer: style, appListStyle: appListStyle, application: selectedApp[0]});
}
handleButtonClick() {
console.log("Application Listing");
this.props.history.push("apps/edit/fdsfdsf343");
} }
remove(imageId) { onAppEditClick(uuid) {
let tmp = this.state.image; this.props.history.push("apps/edit/" + uuid);
console.log(imageId);
let rem = tmp.filter((image) => {
return image.id !== imageId
});
this.setState({image: rem});
} }
closeDrawer() { closeDrawer() {
@ -196,6 +207,12 @@ class ApplicationListing extends Component {
this.setState({drawer: style, appListStyle: appListStyle}); this.setState({drawer: style, appListStyle: appListStyle});
} }
getSelectedApplication(uuid) {
return this.state.searchedApplications.filter(application => {
return application.uuid === uuid;
});
}
render() { render() {
return ( return (
@ -213,7 +230,7 @@ class ApplicationListing extends Component {
<Col> <Col>
<Table striped hover> <Table striped hover>
<thead> <thead>
<tr> <tr className="app-list-table-header">
<th></th> <th></th>
{/* TODO: Remove console.log and add sort method. */} {/* TODO: Remove console.log and add sort method. */}
<th onClick={() => { <th onClick={() => {
@ -228,25 +245,24 @@ class ApplicationListing extends Component {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{this.applications.map( {this.state.searchedApplications.map(
(application) => { (application) => {
return ( return (
<tr key={application.id} onClick={this.onRowClick}> <tr key={application.uuid} onClick={() => this.onRowClick(application.uuid)}>
<td> <td data={application.uuid}>
{/* TODO: Move this styles to css. */} {/* TODO: Move this styles to css. */}
<img <img
src={application.icon}
height='50px' height='50px'
width='50px' width='50px'
style={{border: 'solid 1px black', borderRadius: "100%"}} style={{border: 'solid 1px black', borderRadius: "100%"}}
/> />
</td> </td>
<td>{application.applicationName}</td> <td>{application.name}</td>
<td>{application.category}</td> <td>{application.category.name}</td>
<td>{application.platform}</td> <td>{application.platform.name}</td>
<td>{application.status}</td> <td>{application.currentLifecycle.lifecycleState.name}</td>
<td> <td>
<Button id="secondary-button" onClick={this.handleButtonClick}> <Button id="secondary-button" onClick={() => this.onAppEditClick(application.uuid)}>
<i className="fw fw-edit"></i> <i className="fw fw-edit"></i>
</Button> </Button>
</td> </td>
@ -259,7 +275,7 @@ class ApplicationListing extends Component {
</Col> </Col>
</Row> </Row>
<Drawer onClose={this.closeDrawer.bind(this)} style={this.state.drawer}> <Drawer onClose={this.closeDrawer.bind(this)} style={this.state.drawer}>
<ApplicationView/> <ApplicationView application={this.state.application}/>
</Drawer> </Drawer>
</div> </div>
); );

@ -21,7 +21,7 @@ import {withRouter} from 'react-router-dom';
import AuthHandler from "../../../api/authHandler"; import AuthHandler from "../../../api/authHandler";
import {Step1, Step2, Step3, Step4} from './CreateSteps/index'; import {Step1, Step2, Step3, Step4} from './CreateSteps/index';
import ApplicationMgtApi from '../../../api/applicationMgtApi'; import ApplicationMgtApi from '../../../api/applicationMgtApi';
import {Button, Col, Modal, ModalBody, ModalFooter, ModalHeader, Row} from 'reactstrap'; import {Col, Modal, ModalBody, ModalHeader, Row} from 'reactstrap';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
/** /**
@ -49,7 +49,11 @@ class ApplicationCreate extends Component {
finished: false, finished: false,
stepIndex: 0, stepIndex: 0,
stepData: [], stepData: [],
isDialogOpen: false isDialogOpen: false,
generalInfo: {},
platform: {},
screenshots: {},
release: {}
}; };
} }
@ -61,10 +65,11 @@ class ApplicationCreate extends Component {
this.setState({open: this.props.open}); this.setState({open: this.props.open});
} }
/**
* Resets the form and closes the modal.
* */
onClose() { onClose() {
this.setState({stepIndex: 0}, this.props.close()); this.setState({stepIndex: 0, generalInfo: {}, platform: {}, screenshots: {}, release: {}}, this.props.close());
} }
/** /**
@ -111,7 +116,6 @@ class ApplicationCreate extends Component {
console.log(this.state.stepIndex); console.log(this.state.stepIndex);
const {stepIndex} = this.state; const {stepIndex} = this.state;
if (stepIndex > 0) { if (stepIndex > 0) {
this.removeStepData();
this.setState({stepIndex: stepIndex - 1, finished: false}); this.setState({stepIndex: stepIndex - 1, finished: false});
} }
}; };
@ -123,10 +127,24 @@ class ApplicationCreate extends Component {
* */ * */
setStepData(step, data) { setStepData(step, data) {
console.log(step, data, this.state.stepData); //TODO: Remove this console.log(step, data, this.state.stepData); //TODO: Remove this
let tmpStepData = this.state.stepData; switch (step) {
tmpStepData.push({step: step, data: data}); case "generalInfo": {
this.setState({generalInfo: data}, this.onNextClick());
this.setState({stepData: tmpStepData}, this.onNextClick()) break;
}
case "platform": {
this.setState({platform: data}, this.onNextClick());
break;
}
case "screenshots": {
this.setState({screenshots: data}, this.onNextClick());
break;
}
case "release": {
this.setState({release: data}, this.onNextClick());
break;
}
}
}; };
/** /**
@ -135,9 +153,10 @@ class ApplicationCreate extends Component {
removeStepData() { removeStepData() {
let tempData = this.state.stepData; let tempData = this.state.stepData;
tempData.pop(); tempData.pop();
this.setState({stepData: tempData}); this.setState({stepData: tempData, stepIndex: 0});
}; };
/* ----------------- Deprecated ----------------- */
/** /**
* Handles the Yes button in app creation cancellation dialog. * Handles the Yes button in app creation cancellation dialog.
* Clears all the form data and reset the wizard. * Clears all the form data and reset the wizard.
@ -154,6 +173,8 @@ class ApplicationCreate extends Component {
this.setState({isDialogOpen: false}); this.setState({isDialogOpen: false});
}; };
/* ---------------------------------------------- */
/** /**
* Defines all the Steps in the stepper. (Wizard) * Defines all the Steps in the stepper. (Wizard)
* *
@ -168,35 +189,36 @@ class ApplicationCreate extends Component {
case 0: case 0:
return ( return (
<Step1 <Step1
handleNext={this.onNextClick} defaultData={this.state.generalInfo}
setData={this.setStepData} setStepData={this.setStepData}
removeData={this.removeStepData} close={this.onClose}
/> />
); );
case 1: case 1:
return ( return (
<Step2 <Step2
handleNext={this.onNextClick} defaultData={this.state.platform}
handlePrev={this.onPrevClick} handlePrev={this.onPrevClick}
setData={this.setStepData} setStepData={this.setStepData}
removeData={this.removeStepData} close={this.onClose}
/> />
); );
case 2: case 2:
return ( return (
<Step3 <Step3
handleFinish={this.onNextClick} defaultData={this.state.screenshots}
handlePrev={this.onPrevClick} handlePrev={this.onPrevClick}
setData={this.setStepData} setStepData={this.setStepData}
removeData={this.removeStepData} close={this.onClose}
/> />
); );
case 3: { case 3: {
return ( return (
<Step4 <Step4
handleNext={this.onNextClick} defaultData={this.state.release}
setData={this.setStepData} handlePrev={this.onPrevClick}
removeData={this.removeStepData} setStepData={this.setStepData}
close={this.onClose}
/> />
) )
} }
@ -252,22 +274,6 @@ class ApplicationCreate extends Component {
</Col> </Col>
</Row> </Row>
</ModalBody> </ModalBody>
<ModalFooter>
{stepIndex === 0 ? <div/> :
<Button color="primary" onClick={this.onPrevClick}>
<FormattedMessage id="Back" defaultMessage="Back"/>
</Button>}
<Button color="secondary" onClick={this.onClose}>
<FormattedMessage id="Cancel" defaultMessage="Cancel"/>
</Button>
{finished ?
<Button color="primary" onClick={this.onSubmit}>
<FormattedMessage id="Finish" defaultMessage="Finish" />
</Button> :
<Button color="primary" onClick={this.onNextClick}>
<FormattedMessage id="Continue" defaultMessage="Continue"/>
</Button>}
</ModalFooter>
</Modal> </Modal>
</div>); </div>);
} }

@ -20,6 +20,7 @@ import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {Badge, FormGroup, Input, Label} from 'reactstrap'; import {Badge, FormGroup, Input, Label} from 'reactstrap';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
import {Badge, Button, Form, FormGroup, Input, Label, ModalFooter} from 'reactstrap';
/** /**
* The Second step of application create wizard. * The Second step of application create wizard.
@ -42,22 +43,32 @@ import {FormattedMessage} from 'react-intl';
class Step1 extends Component { class Step1 extends Component {
constructor() { constructor() {
super(); super();
this.onTextFieldChange = this.onTextFieldChange.bind(this);
this.setStepData = this.setStepData.bind(this);
this.onCancelClick = this.onCancelClick.bind(this);
this.onVisibilityChange = this.onVisibilityChange.bind(this);
this.onVisibilityItemSelect = this.onVisibilityItemSelect.bind(this);
this.handleRequestDelete = this.handleRequestDelete.bind(this);
this.state = { this.state = {
tags: [], tags: [],
icon: [], name: "",
title: "",
errors: {}, errors: {},
banner: [],
defValue: "", defValue: "",
category: 0, category: 0,
visibility: 0, visibility: "",
description: "", description: ""
screenshots: [],
identifier: "",
shortDescription: ""
}; };
} }
componentWillMount() {
const defaultVals = this.props.defaultData;
if(defaultVals) {
this.setState(defaultVals);
}
}
/** /**
* Create a tag on Enter key press and set it to the state. * Create a tag on Enter key press and set it to the state.
* Clears the tags text field. * Clears the tags text field.
@ -85,48 +96,101 @@ class Step1 extends Component {
* Handles Chip delete function. * Handles Chip delete function.
* Removes the tag from state.tags * Removes the tag from state.tags
* */ * */
handleRequestDelete(event) { handleRequestDelete(key) {
this.chipData = this.state.tags; let chipData = this.state.tags;
console.log(event.target); const chipToDelete = chipData.map((chip) => chip.key).indexOf(key);
const chipToDelete = this.chipData.map((chip) => chip.value).indexOf(event.target.value); chipData.splice(chipToDelete, 1);
this.chipData.splice(chipToDelete, 1); this.setState({tags: chipData});
this.setState({tags: this.chipData});
}; };
/** /**
* Creates an object with the current step data and persist in the parent. * Creates an object with the current step data and persist in the parent.
* */ * */
setStepData() { setStepData() {
let stepData = {}; const {name, description, tags, visibility} = this.state;
this.props.setData("step1", {step: stepData}); let stepData = {
name: name,
description: description,
tags: tags,
visibility: visibility
};
this.props.setStepData("generalInfo", stepData);
}; };
onCancelClick() {
this.props.close();
}
/** /**
* Set text field values to state. * Set text field values to state.
* */ * */
onTextFieldChange(event, value) { onTextFieldChange(event) {
let field = event.target.id; let field = event.target.name;
console.log(field, event.target.value);
switch (field) { switch (field) {
case "name": { case "appName": {
this.setState({name: value}); this.setState({name: event.target.value});
break; break;
} }
case "shortDescription": { case "appDescription": {
this.setState({shortDescription: value}); this.setState({description: event.target.value});
break; break;
} }
case "description": {
this.setState({description: value});
break;
} }
case "identifier": { };
this.setState({identifier: value});
break; onVisibilityChange(event) {
console.log(event.target.value);
this.setState({visibility: event.target.value});
} }
onVisibilityItemSelect(event) {
} }
};
render() { render() {
const {visibility} = this.state;
let visibilityItem = () => {
switch (visibility) {
case("public"): {
return <div/>
}
case("roles"): {
return <FormGroup>
<Input
type="select"
name="visibility-item"
id="app-visibility-item"
onChange={this.onVisibilityItemSelect}
>
<option id="app-visibility-default" disabled selected>Select the Roles.</option>
<option><Input type="checkbox" />Role1</option>
<option>Role2</option>
</Input>
</FormGroup>
}
case ("groups"): {
return <FormGroup>
<Input
type="select"
name="visibility-item"
id="app-visibility-item"
onChange={this.onVisibilityItemSelect}
>
<option id="app-visibility-default" disabled selected>Select the Groups.</option>
<option>Group1</option>
<option>Group2</option>
</Input>
</FormGroup>
}
default: {
return <div/>
}
}
};
return ( return (
<div className="createStep2Content"> <div className="createStep2Content">
<div> <div>
@ -135,13 +199,27 @@ class Step1 extends Component {
<Label for="app-title"> <Label for="app-title">
<FormattedMessage id='Title' defaultMessage='Title'/>* <FormattedMessage id='Title' defaultMessage='Title'/>*
</Label> </Label>
<Input required type="text" name="appName" id="app-title"/> <Input
required
type="text"
name="appName"
id="app-title"
value={this.state.name}
onChange={this.onTextFieldChange}
/>
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<Label for="app-description"> <Label for="app-description">
<FormattedMessage id='Description' defaultMessage='Description'/>* <FormattedMessage id='Description' defaultMessage='Description'/>*
</Label> </Label>
<Input required type="textarea" name="appDescription" id="app-description"/> <Input
required
type="textarea"
name="appDescription"
id="app-description"
value={this.state.description}
onChange={this.onTextFieldChange}
/>
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<Label for="app-category"> <Label for="app-category">
@ -155,12 +233,25 @@ class Step1 extends Component {
<Label for="app-visibility"> <Label for="app-visibility">
<FormattedMessage id='Visibility' defaultMessage='Visibility'/> <FormattedMessage id='Visibility' defaultMessage='Visibility'/>
</Label> </Label>
<Input type="select" name="visibility" id="app-visibility"> <Form inline>
<option><FormattedMessage id='Devices' defaultMessage='Devices'/></option> <FormGroup>
<option><FormattedMessage id='Roles' defaultMessage='Roles'/></option> <Input
<option><FormattedMessage id='Groups' defaultMessage='Groups'/></option> type="select"
name="visibility"
id="app-visibility"
onChange={this.onVisibilityChange}
>
<option id="app-visibility-default" disabled selected>Select the App Visibility
Option.
</option>
<option key={1}><FormattedMessage id='Devices' defaultMessage='Devices'/></option>
<option key={2}><FormattedMessage id='Roles' defaultMessage='Roles'/></option>
<option key={3}><FormattedMessage id='Groups' defaultMessage='Groups'/></option>
</Input> </Input>
</FormGroup> </FormGroup>
{visibilityItem()}
</Form>
</FormGroup>
<FormGroup> <FormGroup>
<Label for="app-tags"><FormattedMessage id='Tags' defaultMessage='Tags'/>*</Label> <Label for="app-tags"><FormattedMessage id='Tags' defaultMessage='Tags'/>*</Label>
<Input <Input
@ -176,9 +267,10 @@ class Step1 extends Component {
{this.state.tags.map(tag => { {this.state.tags.map(tag => {
return ( return (
<Badge <Badge
style={{margin: '0 2px 0 2px'}} style={{margin: '0 2px 0 2px', backgroundColor: 'blue', height: '20px'}}
value={tag.value} value={tag.key}
onClick={this.handleRequestDelete.bind(this)} key={tag.key}
onClick={() => this.handleRequestDelete(tag.key)}
> >
{tag.value} {tag.value}
</Badge> </Badge>
@ -189,6 +281,10 @@ class Step1 extends Component {
</FormGroup> </FormGroup>
</div> </div>
</div> </div>
<ModalFooter>
<Button color="danger" onClick={this.onCancelClick}>Cancel</Button>
<Button color="primary" onClick={this.setStepData}>Continue</Button>
</ModalFooter>
</div> </div>
); );
} }

@ -20,7 +20,7 @@ import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import AuthHandler from "../../../../api/authHandler"; import AuthHandler from "../../../../api/authHandler";
import PlatformMgtApi from "../../../../api/platformMgtApi"; import PlatformMgtApi from "../../../../api/platformMgtApi";
import {FormGroup, Input, Label} from 'reactstrap'; import {Button, FormGroup, Input, Label, ModalFooter} from 'reactstrap';
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
/** /**
@ -41,24 +41,28 @@ class Step2 extends Component {
super(); super();
this.setPlatforms = this.setPlatforms.bind(this); this.setPlatforms = this.setPlatforms.bind(this);
this.setStepData = this.setStepData.bind(this); this.setStepData = this.setStepData.bind(this);
this.onCancelClick = this.onCancelClick.bind(this);
this.onBackClick = this.onBackClick.bind(this);
this.platforms = []; this.platforms = [];
this.state = { this.state = {
finished: false,
stepIndex: 0,
store: 1, store: 1,
platformSelectedIndex: 0, platformSelectedIndex: 0,
platform: "", platform: "",
platforms: [], platforms: []
stepData: [],
title: "",
titleError: ""
}; };
} }
componentWillMount() {
const {defaultData} = this.props;
if (defaultData) {
this.setState(defaultData);
}
}
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 => {
console.log(response);
this.setPlatforms(response.data); this.setPlatforms(response.data);
}).catch(err => { }).catch(err => {
AuthHandler.unauthorizedErrorHandler(err); AuthHandler.unauthorizedErrorHandler(err);
@ -83,18 +87,26 @@ class Step2 extends Component {
* Persist the current form data to the state. * Persist the current form data to the state.
* */ * */
setStepData() { setStepData() {
let step = { const {store, platform} = this.state;
store: this.state.store, let data = {
platform: this.state.platforms[this.state.platformSelectedIndex] store: store,
platform: platform[0]
}; };
this.props.setData("step2", {step: step}); this.props.setStepData("platform", data);
}
onCancelClick() {
this.props.close();
}
onBackClick() {
this.props.handlePrev();
} }
/** /**
* Triggers when changing the Platform selection. * Triggers when changing the Platform selection.
* */ * */
onChangePlatform(event) { onChangePlatform(event) {
console.log(event.target.value, this.state.platforms);
let id = event.target.value; let id = event.target.value;
let selectedPlatform = this.state.platforms.filter((platform) => { let selectedPlatform = this.state.platforms.filter((platform) => {
return platform.identifier === id; return platform.identifier === id;
@ -122,16 +134,27 @@ class Step2 extends Component {
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<Label for="store"><FormattedMessage id='Platform' defaultMessage='Platform'/></Label> <Label for="store"><FormattedMessage id='Platform' defaultMessage='Platform'/></Label>
<Input type="select" name="store" onChange={this.onChangePlatform.bind(this)}> <Input
required
type="select"
name="store"
onChange={this.onChangePlatform.bind(this)}
>
<option id="app-visibility-default" disabled selected>Select the Application Platform</option>
{this.state.platforms.length > 0 ? this.state.platforms.map(platform => { {this.state.platforms.length > 0 ? this.state.platforms.map(platform => {
return ( return (
<option value={platform.identifier}> <option value={platform.identifier} key={platform.identifier}>
{platform.name} {platform.name}
</option> </option>
) )
}) : <option><FormattedMessage id='No.Platform' defaultMessage='No Platforms'/></option>} }) : <option><FormattedMessage id='No.Platform' defaultMessage='No Platforms'/></option>}
</Input> </Input>
</FormGroup> </FormGroup>
<ModalFooter>
<Button color="primary" onClick={this.onBackClick}>Back</Button>
<Button color="danger" onClick={this.onCancelClick}>Cancel</Button>
<Button color="primary" onClick={this.setStepData}>Continue</Button>
</ModalFooter>
</div> </div>
); );
} }

@ -19,7 +19,7 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Dropzone from 'react-dropzone'; import Dropzone from 'react-dropzone';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {FormGroup, Label} from 'reactstrap'; import {Button, FormGroup, Label, ModalFooter} from 'reactstrap';
import AppImage from "../../../UIComponents/AppImage/AppImage"; import AppImage from "../../../UIComponents/AppImage/AppImage";
import {FormattedMessage} from 'react-intl'; import {FormattedMessage} from 'react-intl';
@ -40,22 +40,23 @@ import {FormattedMessage} from 'react-intl';
class Step3 extends Component { class Step3 extends Component {
constructor() { constructor() {
super(); super();
this.setStepData = this.setStepData.bind(this);
this.onBackClick = this.onBackClick.bind(this);
this.onCancelClick = this.onCancelClick.bind(this);
this.state = { this.state = {
tags: [],
icon: [], icon: [],
title: "",
errors: {}, errors: {},
banner: [], banner: [],
defValue: "",
category: 0,
visibility: 0,
description: "",
screenshots: [], screenshots: [],
identifier: "",
shortDescription: ""
}; };
} }
componentWillMount() {
const {defaultData} = this.props;
this.setState(defaultData);
}
/** /**
* Handles Chip delete function. * Handles Chip delete function.
* Removes the tag from state.tags * Removes the tag from state.tags
@ -72,15 +73,26 @@ class Step3 extends Component {
* Creates an object with the current step data and persist in the parent. * Creates an object with the current step data and persist in the parent.
* */ * */
setStepData() { setStepData() {
const {icon, banner, screenshots} = this.state;
let stepData = { let stepData = {
icon: this.state.icon, icon: icon,
banner: this.state.banner, banner: banner,
screenshots: this.state.screenshots screenshots: screenshots
}; };
this.props.setData("step2", {step: stepData}); this.props.setStepData("screenshots", stepData);
}; };
onCancelClick() {
this.props.close();
}
onBackClick() {
this.props.handlePrev();
}
/** /**
* Removed user uploaded banner. * Removed user uploaded banner.
* */ * */
@ -126,7 +138,6 @@ class Step3 extends Component {
onDrop={(screenshots, rejected) => { onDrop={(screenshots, rejected) => {
let tmpScreenshots = this.state.screenshots; let tmpScreenshots = this.state.screenshots;
tmpScreenshots.push(screenshots); tmpScreenshots.push(screenshots);
console.log(screenshots); //TODO: Remove this
this.setState({ this.setState({
screenshots: tmpScreenshots screenshots: tmpScreenshots
}); });
@ -191,6 +202,11 @@ class Step3 extends Component {
</FormGroup> </FormGroup>
</div> </div>
</div> </div>
<ModalFooter>
<Button color="primary" onClick={this.onBackClick}>Back</Button>
<Button color="danger" onClick={this.onCancelClick}>Cancel</Button>
<Button color="primary" onClick={this.setStepData}>Continue</Button>
</ModalFooter>
</div> </div>
); );
} }

@ -18,7 +18,7 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {Collapse, FormGroup, Input, Label, FormText} from 'reactstrap'; import {Button, Collapse, FormGroup, FormText, Input, Label, ModalFooter} from 'reactstrap';
import Switch from '../../../UIComponents/Switch/Switch' import Switch from '../../../UIComponents/Switch/Switch'
/** /**
@ -47,8 +47,8 @@ class Step4 extends Component {
constructor() { constructor() {
super(); super();
this.handleToggle = this.handleToggle.bind(this); this.handleToggle = this.handleToggle.bind(this);
this.handlePrev = this.handlePrev.bind(this); this.onCancelClick = this.onCancelClick.bind(this);
this.handleToggle = this.handleToggle.bind(this); this.onBackClick = this.onBackClick.bind(this);
this.handleFinish = this.handleFinish.bind(this); this.handleFinish = this.handleFinish.bind(this);
this.state = { this.state = {
showForm: false, showForm: false,
@ -66,13 +66,18 @@ class Step4 extends Component {
this.props.handleFinish(); this.props.handleFinish();
} }
/** onCancelClick() {
* Invokes Prev button click. this.props.close();
* */ }
handlePrev() {
onBackClick() {
this.props.handlePrev(); this.props.handlePrev();
} }
onSubmit() {
}
/** /**
* Handles release application selection. * Handles release application selection.
* */ * */
@ -140,6 +145,11 @@ class Step4 extends Component {
</FormGroup> </FormGroup>
</Collapse> </Collapse>
</div> </div>
<ModalFooter>
<Button color="primary" onClick={this.onBackClick}>Back</Button>
<Button color="danger" onClick={this.onCancelClick}>Cancel</Button>
<Button color="primary" onClick={this.onSubmit}>Finish</Button>
</ModalFooter>
</div> </div>
); );
} }

@ -89,6 +89,7 @@ class ApplicationEdit extends Component {
<FormattedMessage id="Application.Name" defaultMessage="Application Name"/> <FormattedMessage id="Application.Name" defaultMessage="Application Name"/>
</Col> </Col>
</Row> </Row>
<hr/>
<Row id="application-edit-main-container"> <Row id="application-edit-main-container">
<Col xs="3"> <Col xs="3">
<div className="tab"> <div className="tab">

@ -47,24 +47,25 @@ class ApplicationView extends Component {
} }
render() { render() {
const platform = this.state.application; if (this.state.application.length === 0) {
console.log(platform); return <div/>
} else {
const app = this.state.application;
console.log(app);
return ( return (
<div id="application-view-content"> <div id="application-view-content">
<div id="application-view-row"> <div id="application-view-row">
<Row> <Row>
<Col> <Col>
<div id="app-icon"> <div id="app-icon">
</div> </div>
</Col> </Col>
<Col> <Col>
<Row> <Row>
<span><strong>Facebook</strong></span> <span><strong>{app.name}</strong></span>
</Row> </Row>
<Row> <Row>
<span className="app-updated-date">Last updated on 2017-09-23</span> <span className="app-updated-date">Last updated on {app.modifiedAt}</span>
</Row> </Row>
</Col> </Col>
</Row> </Row>
@ -83,7 +84,7 @@ class ApplicationView extends Component {
<i className="fw fw-star"></i> <i className="fw fw-star"></i>
</Col> </Col>
<Col> <Col>
<a href="#">View in Store</a> <p><a href="#">View in Store</a></p>
</Col> </Col>
</Row> </Row>
</div> </div>
@ -96,7 +97,7 @@ class ApplicationView extends Component {
</strong></span> </strong></span>
</Col> </Col>
<Col> <Col>
<p>sdfjlkdsjfsjdfjsdf sfjdslkjfdsflkjdsfslkdjfl j</p> <p>{app.description}</p>
</Col> </Col>
</Row> </Row>
<Row> <Row>
@ -131,7 +132,10 @@ class ApplicationView extends Component {
</Row> </Row>
</div> </div>
</div> </div>
); );
}
} }
} }

@ -18,21 +18,28 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
/** /**
* Platform view component. * Platform component.
* In Platform listing, this component will be displayed as cards.
* */ * */
class PlatformView extends Component { class Platform extends Component {
constructor() { constructor() {
super(); super();
} }
render() { render() {
const {platform} = this.props;
console.log(platform);
return ( return (
<div> <div id="platform-content">
Platform View <ul>
<li>Name: {platform.name}</li>
<li>Description: {platform.description}</li>
<li>Status: {platform.enabled}</li>
</ul>
</div> </div>
); );
} }
} }
export default PlatformView; export default Platform;

@ -15,416 +15,58 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * 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 React, {Component} from 'react';
import Toggle from 'material-ui/Toggle'; import {Button, FormGroup, Label, Modal, ModalBody, ModalFooter, ModalHeader, Input} from "reactstrap";
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 PlatformMgtApi from '../../api/platformMgtApi';
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';
/** /**
* Platform Create component. * Platform view component.
* Contains following components:
* * Platform Name
* * Platform Description
* * Platform Icon
* * Whether the platform needs an app to be installed.
* * Whether the platform is enabled by default.
* * Whether the platform is shared with tenants.
* */ * */
class PlatformCreate extends Component { class PlatformCreate extends Component {
constructor() { constructor() {
super(); super();
this.onCreatePlatform = this.onCreatePlatform.bind(this); this.onCancelClick = this.onCancelClick.bind(this);
this.handleToggle = this.handleToggle.bind(this);
this.addProperty = this.addProperty.bind(this);
this.addTags = this.addTags.bind(this);
this.clearForm = this.clearForm.bind(this);
this.onPropertySelect = this.onPropertySelect.bind(this);
this.handleTagChange = this.handleTagChange.bind(this);
this.removeIcon = this.removeIcon.bind(this);
this.onTextChange = this.onTextChange.bind(this);
this.renderChip = this.renderChip.bind(this);
this.removeProperty = this.removeProperty.bind(this);
this.state = { this.state = {
tags: [], open: false
defValue: "",
enabled: true,
allTenants: false,
files: [],
platformProperties: [],
selectedProperty: 0,
name: "",
description: "",
property: "",
icon: [],
identifier: "",
propertyTypes: [
{key: 0, value: 'String'},
{key: 1, value: 'Number'},
{key: 2, value: 'Boolean'},
{key: 3, value: 'File'}]
};
}
/**
* Handles toggle button actions.
* One method is used for all the toggle buttons and, each toggle is identified by the id.
* */
handleToggle(event) {
switch (event.target.id) {
case "enabled" : {
let enabled = this.state.enabled;
this.setState({enabled: !enabled});
break;
}
case "tenant" : {
let allTenants = this.state.allTenants;
this.setState({allTenants: !allTenants});
break;
}
}
}
/**
* Triggers the onChange action on property type selection.
* */
onPropertySelect(event, index, value) {
console.log(this.state.propertyTypes[value]);
this.setState({selectedProperty: value});
}
/**
* Handles Chip delete function.
* Removes the tag from state.tags
* */
handleTagDelete(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});
}
/**
* 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: ""});
} }
} }
/**
* Creates Chip array from state.tags.
* */
renderChip(data) {
return (
<Chip
key={data.key}
onRequestDelete={() => this.handleTagDelete(data.key)}
style={this.styles.chip}
>
{data.value}
</Chip>
);
}
/**
* Set the value for tag.
* */
handleTagChange(event) {
let defaultValue = this.state.defValue;
defaultValue = event.target.value;
this.setState({defValue: defaultValue})
}
/** componentWillReceiveProps(props, nextprops) {
* Remove the selected property from the property list. this.setState({open: props.open})
* */
removeProperty(property) {
let properties = this.state.platformProperties;
properties.splice(properties.indexOf(property), 1);
this.setState({platformProperties: properties});
} }
/** componentWillMount() {
* Add a new platform property. this.setState({open: this.props.open});
* */
addProperty() {
let property = this.state.property;
let selected = this.state.selectedProperty;
this.setState({
platformProperties:
this.state.platformProperties.concat([
{
key: property,
value: this.state.propertyTypes[selected].value
}]),
property: "",
selectedProperty: 0
});
} }
/** onCancelClick() {
* Triggers in onChange event of text fields. this.setState({open: false})
* Text fields are identified by their ids and the value will be persisted in the component state.
* */
onTextChange(event, value) {
let property = this.state.property;
let name = this.state.name;
let description = this.state.description;
let identifier = this.state.identifier;
switch (event.target.id) {
case "name": {
name = value;
this.setState({name: name});
break;
}
case "description": {
description = value;
this.setState({description: description});
break;
}
case "property": {
property = value;
this.setState({property: property});
break;
}
case "identifier": {
identifier = value;
this.setState({identifier: identifier});
}
}
};
/**
* Create platform object and call the create platform api.
* */
onCreatePlatform(event) {
//Call the platform create api.
event.preventDefault();
let platform = {};
platform.identifier = this.state.identifier;
platform.name = this.state.name;
platform.description = this.state.description;
platform.tags = this.state.tags;
platform.properties = this.state.platformProperties;
platform.icon = this.state.icon;
platform.enabled = this.state.enabled;
platform.allTenants = this.state.allTenants;
platform.defaultTenantMapping = true;
PlatformMgtApi.createPlatform(platform);
}
/**
* Remove the uploaded icon.
* */
removeIcon(event) {
event.preventDefault();
this.setState({icon: []});
}
/**
* Clears the user entered values in the form.
* */
clearForm(event) {
event.preventDefault();
this.setState({
enabled: true,
allTenants: false,
files: [],
platformProperties: [],
selectedProperty: 0,
name: "",
description: "",
property: "",
})
} }
render() { render() {
const {
platformProperties,
allTenants,
enabled,
selectedProperty,
propertyTypes,
name,
tags,
defValue,
description,
identifier,
property
} = this.state;
return ( return (
<div className="middle createplatformmiddle">
<Card>
<CardTitle title="Create Platform"/>
<CardActions>
<div className="createplatformcardaction">
<form>
<TextField
hintText="Unique Identifier for Platform."
id="identifier"
floatingLabelText="Identifier*"
floatingLabelFixed={true}
value={identifier}
onChange={this.onTextChange}
/>
<br/>
<TextField
hintText="Enter the Platform Name."
id="name"
floatingLabelText="Name*"
floatingLabelFixed={true}
value={name}
onChange={this.onTextChange}
/>
<br/>
<TextField
id="description"
hintText="Enter the Platform Description."
floatingLabelText="Description*"
floatingLabelFixed={true}
multiLine={true}
rows={2}
value={description}
onChange={this.onTextChange}
/>
<br/>
<br/>
<Toggle
id="tenant"
label="Shared with all Tenants"
labelPosition="right"
onToggle={this.handleToggle}
toggled={allTenants}
/>
<br/>
<Toggle
id="enabled"
label="Enabled"
labelPosition="right"
onToggle={this.handleToggle}
toggled={enabled}
/>
<br/>
<TextField
id="tags"
hintText="Enter Platform tags.."
floatingLabelText="Tags*"
floatingLabelFixed={true}
value={defValue}
onChange={this.handleTagChange}
onKeyPress={this.addTags}
/>
<br/>
<div className="createPlatformTagWrapper">
{tags.map(this.renderChip, this)}
</div>
<br/>
<div> <div>
<p className="createplatformproperties">Platform Properties</p> <Modal isOpen={this.state.open} toggle={this.toggle} id="platform-create-modal" backdrop={'static'}>
<div id="property-container"> <ModalHeader>Create Platform</ModalHeader>
{platformProperties.map((p) => { <ModalBody>
return <div key={p.key}>{p.key} : {p.value} <FormGroup>
<IconButton onClick={this.removeProperty.bind(this, p)}> <Label for="platform-name">Name*</Label>
<Close className="createplatformpropertyclose"/> <Input required type="text" name="appName" id="platform-name"/>
</IconButton> </FormGroup>
</div> <FormGroup>
})} <Label for="platform-description">Description*</Label>
</div> <Input required type="textarea" name="appName" id="platform-description"/>
<div className="createplatformproperty"> </FormGroup>
<TextField </ModalBody>
id="property" <ModalFooter>
hintText="Property Name" <Button onClick={this.onCancelClick}>Cancel</Button>
floatingLabelText="Platform Property*" <Button color="primary">Create</Button>
floatingLabelFixed={true} </ModalFooter>
value={this.state.property} </Modal>
onChange={this.onTextChange}
/> <em/>
<SelectField
className="createplatformpropertyselect"
floatingLabelText="Property Type"
value={selectedProperty}
floatingLabelFixed={true}
onChange={this.onPropertySelect}>
{propertyTypes.map((type) => {
return <MenuItem key={type.key}
value={type.key}
primaryText={type.value}/>
})}
</SelectField>
<IconButton onClick={this.addProperty}>
<AddCircleOutline/>
</IconButton>
<br/>
</div>
</div>
<div>
<p className="createplatformiconp">Platform Icon*:</p>
<GridList className="createplatformicon" cols={1.1}>
{this.state.icon.map((tile) => (
<GridTile
key={Math.floor(Math.random() * 1000)}
title={tile.name}
actionIcon={
<IconButton onClick={this.removeIcon}>
<Clear/>
</IconButton>}>
<img src={tile.preview}/>
</GridTile>
))}
{this.state.icon.length === 0 ?
<Dropzone
className="createplatformdropzone"
accept="image/jpeg, image/png"
onDrop={(icon, rejected) => {
this.setState({icon, rejected})
}}
>
<p className="createplatformdropzonep">+</p>
</Dropzone> : <div/>}
</GridList>
</div>
<br/>
<RaisedButton
primary={true} label="Create"
onClick={this.onCreatePlatform}/>
<FlatButton label="Cancel" onClick={this.clearForm}/>
</form>
</div>
</CardActions>
</Card>
</div> </div>
); );
} }
} }
PlatformCreate.prototypes = {};
export default PlatformCreate; export default PlatformCreate;

@ -15,145 +15,61 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
import React, {Component} from 'react'; import React, {Component} from 'react';
import {withRouter} from 'react-router-dom'; import {Button, Col, Row} from "reactstrap";
import TextField from 'material-ui/TextField'; import Platform from "./Platform";
import AuthHandler from "../../api/authHandler";
import DataTable from '../UIComponents/DataTable/DataTable';
import PlatformMgtApi from "../../api/platformMgtApi"; import PlatformMgtApi from "../../api/platformMgtApi";
import {Card, CardActions, CardTitle} from 'material-ui/Card'; import AuthHandler from "../../api/authHandler";
import PlatformCreate from "./PlatformCreate";
/** /**
* The App Create Component. * Platform view component.
*
* Application creation is handled through a Wizard. (We use Material UI Stepper.)
*
* In each step, data will be set to the state separately.
* When the wizard is completed, data will be arranged and sent to the api.
* */ * */
class PlatformListing extends Component { class PlatformListing extends Component {
constructor() { constructor() {
super(); super();
this.setPlatforms = this.setPlatforms.bind(this); this.onPlatformCreateClick = this.onPlatformCreateClick.bind(this);
this.state = { this.state = {
platforms: [], platforms: [],
asc: true openModal: false
};
} }
headers = [
{
data_id: "image",
data_type: "image",
sortable: false,
label: ""
},
{
data_id: "platformName",
data_type: String,
sortable: true,
label: "Platform Name",
sort: this.sortData
},
{
data_id: "enabled",
data_type: String,
sortable: false,
label: "Enabled"
},
{
data_id: "fileBased",
data_type: String,
sortable: false,
label: "File Based"
} }
];
componentDidMount() { componentWillMount() {
let platformsPromise = PlatformMgtApi.getPlatforms(); PlatformMgtApi.getPlatforms().then(response => {
platformsPromise.then( console.log(response);
response => { this.setState({platforms: response.data});
let platforms = this.setPlatforms(response.data); }).catch(err => {
this.setState({platforms: platforms});
}
).catch(
err => {
AuthHandler.unauthorizedErrorHandler(err); AuthHandler.unauthorizedErrorHandler(err);
} })
)
}
/**
* Create platform objects from the response which can be displayed in the table.
* */
setPlatforms(platforms) {
let tmpPlatforms = [];
for (let index in platforms) {
let platform = {};
platform.id = platforms[index].identifier;
platform.platformName = platforms[index].name;
platform.enabled = platforms[index].enabled.toString();
platform.fileBased = platforms[index].fileBased.toString();
tmpPlatforms.push(platform)
}
return tmpPlatforms;
}
/**
* Handles the search action.
* When typing in the search bar, this method will be invoked.
* */
searchApplications(word) {
let searchedData = [];
} }
/** onPlatformCreateClick() {
* Handles sort data function and toggles the asc state. this.setState({openModal: true});
* asc: true : sort in ascending order.
* */
sortData() {
let isAsc = this.state.asc;
let datas = isAsc ? this.data.sort(this.compare) : this.data.reverse();
this.setState({data: datas, asc: !isAsc});
}
compare(a, b) {
if (a.applicationName < b.applicationName)
return -1;
if (a.applicationName > b.applicationName)
return 1;
return 0;
}
onRowClick(id) {
//TODO: Remove this
console.log(id)
} }
render() { render() {
return ( return (
<div className='middle listingplatformmiddle'> <div id="platform-listing">
<Card className='listingplatformcard'> <Row>
<TextField hintText="Search" onChange={this.searchApplications.bind(this)} <div className="create-platform">
className='listingplatformsearch'/> <Button id="create-platform-btn" onClick={this.onPlatformCreateClick}>Create Platform</Button>
<CardTitle title="Platforms" className='listingplatformTitle'/> </div>
<CardActions> </Row>
<Row>
</CardActions> <div id="platform-list">
<DataTable {this.state.platforms.map(platform => {
headers={this.headers} return (
data={this.state.platforms} <Platform key={platform.identifier} platform={platform}/>
handleRowClick={this.onRowClick.bind(this)} )
noDataMessage={{type: 'button', text: 'Create Platform'}}/> })}
</Card> </div>
</Row>
<PlatformCreate open={this.state.openModal}/>
</div> </div>
); );
} }
} }
PlatformListing.propTypes = {}; export default PlatformListing;
export default withRouter(PlatformListing);

@ -93,7 +93,7 @@ class DataTable extends Component {
} }
handleBtnClick(id) { handleBtnClick(id) {
this.props.handleButtonClick(id); this.props.onAppEditClick(id);
} }
render() { render() {

@ -63,7 +63,7 @@ class DataTableRow extends Component {
handleBtnClick(event) { handleBtnClick(event) {
event.stopPropagation(); event.stopPropagation();
console.log(event.target['id']) console.log(event.target['id'])
this.props.handleButtonClick(event.target['id']); this.props.onAppEditClick(event.target['id']);
} }
render() { render() {

@ -20,7 +20,7 @@ import qs from 'qs';
import React, {Component} from 'react'; import React, {Component} from 'react';
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 {Button, Card, CardBlock, CardTitle, Col, Form, FormGroup, Input, Label} from 'reactstrap'; import {Button, Card, CardBlock, CardTitle, Form, FormGroup, Input, Label} from 'reactstrap';
/** /**
* The Login Component. * The Login Component.
@ -132,27 +132,32 @@ class Login extends Component {
{/*TODO: Style the components.*/} {/*TODO: Style the components.*/}
<Card id="login-card"> <Card id="login-card">
<CardBlock> <CardBlock>
<CardTitle>WSO2 IoT APP Publisher</CardTitle> <CardTitle>
WSO2 IoT APP Publisher
</CardTitle>
<hr/>
<Form onSubmit={this.handleLogin.bind(this)}> <Form onSubmit={this.handleLogin.bind(this)}>
<FormGroup row> <FormGroup>
<Label for="userName" sm={2}>User Name:</Label> <Label for="userName">User Name:</Label>
<Col sm={10}> <Input
<Input type="text" name="userName" id="userName" placeholder="User Name" type="text"
name="userName"
id="userName"
placeholder="User Name"
onChange={this.onUserNameChange.bind(this)}/> onChange={this.onUserNameChange.bind(this)}/>
</Col>
</FormGroup> </FormGroup>
<FormGroup row> <FormGroup>
<Label for="password" sm={2}>Password:</Label> <Label for="password">Password:</Label>
<Col sm={10}> <Input
<Input type="password" name="text" id="password" placeholder="Password" valid={false}
type="password"
name="text"
id="password"
placeholder="Password"
onChange={this.onPasswordChange.bind(this)}/> onChange={this.onPasswordChange.bind(this)}/>
</Col>
</FormGroup> </FormGroup>
<FormGroup check row> <FormGroup>
<Col sm={{size: 10, offset: 2}}>
<Button type="submit" id="login-btn">Login</Button> <Button type="submit" id="login-btn">Login</Button>
</Col>
</FormGroup> </FormGroup>
</Form> </Form>
</CardBlock> </CardBlock>

Loading…
Cancel
Save