Added tags to platform create page and basic backend integration api implementation.

feature/appm-store/pbac
Menaka Jayawardena 7 years ago
parent 611eb78554
commit b3d2abf99e

@ -11,38 +11,40 @@
"dependencies": {
"axios": "^0.16.2",
"flux": "^3.1.3",
"history": "^4.6.3",
"history": "^4.7.2",
"latest-version": "^3.1.0",
"material-ui": "^0.19.0",
"material-ui": "^0.19.1",
"prop-types": "^15.5.10",
"qs": "^6.5.0",
"react": "^15.6.1",
"react-dom": "^15.6.1",
"react-dropzone": "^4.1.0",
"react-dropzone": "^4.1.2",
"react-images-uploader": "^1.1.0",
"react-material-ui-form-validator": "^0.5.0",
"react-modal": "^2.2.2",
"react-router": "^4.1.2",
"react-router-dom": "^4.1.2",
"react-material-ui-form-validator": "^0.5.1",
"react-modal": "^2.3.2",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-scripts": "1.0.10",
"react-sliding-pane": "^1.2.3",
"react-tap-event-plugin": "^2.0.1"
},
"devDependencies": {
"babel-core": "^6.24.1",
"babel-loader": "^7.0.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-preset-es2015": "^6.24.1",
"chai": "^4.0.2",
"babel-preset-react": "^6.24.1",
"babel-register": "^6.24.1",
"css-loader": "^0.28.2",
"babel-register": "^6.26.0",
"chai": "^4.1.2",
"css-loader": "^0.28.7",
"less": "^2.7.2",
"less-loader": "^4.0.4",
"mocha": "^3.4.1",
"mock-local-storage": "^1.0.2",
"node-sass": "^4.5.3",
"sass-loader": "^6.0.6",
"style-loader": "^0.18.1",
"webpack": "^2.5.0"
"webpack": "^2.7.0"
},
"scripts": {
"start": "react-scripts start",

@ -16,7 +16,7 @@
* under the License.
*/
import './App.css';
import './App.scss';
import React, {Component} from 'react';
import createHistory from 'history/createBrowserHistory';
import {BrowserRouter as Router, Redirect, Route, Switch} from 'react-router-dom'
@ -54,12 +54,21 @@ class Base extends Component {
constructor() {
super();
this.state = {
user: "admin"
user: "s"
}
}
componentWillMount() {
}
componentDidMount() {
}
render() {
if (this.state.user) {
console.log("Have User.");
return (
<div className="container">
<BaseLayout>
@ -69,8 +78,8 @@ class Base extends Component {
<Route exact path={"/assets/apps/create"} component={ApplicationCreate}/>
<Route exact path={"/assets/platforms"} component={PlatformListing}/>
<Route exact path={"/assets/platforms/create"} component={PlatformCreate}/>
<Route exact path={"/assets/apps/:app"} />
<Route exact path={"/assets/apps/:app/edit"} />
<Route exact path={"/assets/apps/:app"}/>
<Route exact path={"/assets/apps/:app/edit"}/>
<Route exact path={"/assets/platforms/:platform"}/>
<Route exact path={"/assets/platforms/:platform/edit"}/>
<Route exact path={"/assets/reviews"}/>
@ -80,8 +89,11 @@ class Base extends Component {
</BaseLayout>
</div>
)
} else {
console.log("No user");
return (<Redirect to={"/login"}/>)
}
return (<Redirect to={"/login"}/>)
}
}

@ -15,3 +15,31 @@
* specific language governing permissions and limitations
* under the License.
*/
'use strict';
import Axios from 'axios';
/**
* Handles all tasks related to Authentication and Authorization.
* Generate access tokens, verify the user has necessary permissions etc.
* */
class AuthHandler {
/**
* Generate client id and client secret to generate access tokens.
* */
login(userName, password) {
Axios.post("https://localhost:9443/auth/application-mgt/v1.0/auth/tokens?userName=admin&password=admin").then()
}
isLoggedIn() {
}
getloggedInUser() {
}
}

@ -15,7 +15,106 @@
* specific language governing permissions and limitations
* under the License.
*/
'use strict';
import Helper from './helpers/AppMgtApiHelpers';
/**
* Defines the list of App Manager APIs.
* */
* Application related apis
* */
export default class Endpoint{
/**
* Api for create an application.
* @param: applicationData: The application data object. This contains an object array of each step data from
* application creation wizard.
*
* From that data array, the proper application object is created and send it to the api.
* */
static createApplication(applicationData) {
console.log("In application create application", applicationData);
Helper.buildApplication(applicationData);
}
/**
* Method to handle application release process.
* */
static releaseApplication() {
}
/**
* Edit created application.
* @param applicationData: The modified application data.
* */
static editApplication(applicationData) {
}
/**
* Get all the created applications for the user.
* */
static getApplications() {
}
/**
* Get specific application.
* @param appId : The application Id.
* */
static getApplication(appId) {
}
/**
* Delete specified application.
* @param appId: The id of the application which is to be deleted.
* */
static deleteApplication(appId) {
}
/**
* Platform related apis
* */
/**
* Create a new Platform
* @param platformData: The platform data object.
* */
static createPlatform(platformData) {
// /api/application-mgt/v1.0/platforms/1.0.0/
// {
// identifier: "${platform_identifier}",
// name: "New Platform",
// description : "New Platform"
// }
}
/**
* Get available platforms
* */
static getPlatforms() {
}
/**
* Get the user specified platform
* @param platformId: The identifier of the platform
* */
static getPlatform(platformId) {
}
/**
* Delete specified platform
* @param platformId: The id of the platform which is to be deleted.
* */
static deletePlatform(platformId) {
}
}

@ -0,0 +1,49 @@
/*
* 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.
*/
'use strict';
/**
* Helper methods for app publisher.
* */
export default class Helper {
/**
* Generate application object from form data passed.
* @param appData: Application data from the application creation form.
* */
static buildApplication(appData) {
let application = {};
let images = {};
for (var step in appData) {
let tmpData = appData[step].data.step;
for (var prop in tmpData) {
if (prop === 'banner' || prop === 'screenshots' || prop === 'icon') {
images[prop] = tmpData[prop];
} else {
application[prop] = tmpData[prop];
}
}
}
console.log(application, images);
}
}

@ -15,3 +15,17 @@
* specific language governing permissions and limitations
* under the License.
*/
scopes = 'perm:application:get perm:application:create perm:application:update perm:application-mgt:login' +
' perm:application:delete perm:platform:add perm:platform:remove perm:roles:view perm:devices:view';
TOKEN_ENDPOINT = '/token';
DYNAMIC_CLIENT_REGISTER_ENDPOINT = '/api-application-registration/register';
appManagerEndpoints = {
GET_ALL_APPS: '/api/application-mgt/v1.0/applications/1.0.0/',
CREATE_APP: '/api/application-mgt/v1.0/applications/1.0.0/',
UPLOAD_IMAGES: '/api/application-mgt/v1.0/applications/1.0.0/upload-image-artifacts/', //+appId
};

@ -18,6 +18,7 @@
import React, {Component} from 'react';
import Dialog from 'material-ui/Dialog';
import Endpoint from '../../api/Endpoints';
import {withRouter} from 'react-router-dom';
import FlatButton from 'material-ui/FlatButton';
import {Step1, Step2, Step3} from './CreateSteps';
@ -80,6 +81,8 @@ class ApplicationCreate extends Component {
* */
handleSubmit = () => {
console.log(this.state.stepData);
Endpoint.createApplication(this.state.stepData);
};
/**
@ -164,11 +167,10 @@ class ApplicationCreate extends Component {
setData={this.setStepData}
removeData={this.removeStepData}/>;
default:
return 'You\'re a long way from home sonny jim!';
return <div></div>;
}
}
render() {
const {finished, stepIndex} = this.state;
const contentStyle = {margin: '0 16px'};
@ -189,7 +191,6 @@ class ApplicationCreate extends Component {
/>,
];
return (
<div className="middle createapplicationmiddle">
<Card className="creataapplicationcard">

@ -56,16 +56,16 @@ class Step2 extends Component {
super();
this.state = {
tags: [],
icon: [],
title: "",
errors: {},
banner: [],
defValue: "",
category: 0,
visibility: 0,
errors: {},
title: "",
shortDescription: "",
description: "",
banner: [],
screenshots: [],
icon: []
shortDescription: ""
};
this.scriptId = "application-create-step2";
}
@ -243,13 +243,14 @@ class Step2 extends Component {
* */
_setStepData() {
let stepData = {
title: this.state.title,
description: this.state.description,
shortDescription: this.state.shortDescription,
tags: this.state.tags,
icon: this.state.icon,
title: this.state.title,
banner: this.state.banner,
category: this.state.category,
screenshots: this.state.screenshots,
icon: this.state.icon
description: this.state.description,
shortDescription: this.state.shortDescription
};
this.props.setData("step2", {step: stepData});
@ -346,7 +347,7 @@ class Step2 extends Component {
<TextField
id="tags"
errorText={this.state.errors["tags"]}
hintText="Enter application tags.."
hintText="Enter Application tags.."
floatingLabelText="Tags*"
floatingLabelFixed={true}
value={this.state.defValue}

@ -17,6 +17,8 @@
*/
import PropTypes from 'prop-types';
import Axios from 'axios';
import Chip from 'material-ui/Chip';
import Dropzone from 'react-dropzone';
import React, {Component} from 'react';
import Toggle from 'material-ui/Toggle';
@ -48,6 +50,8 @@ class PlatformCreate extends Component {
constructor() {
super();
this.state = {
tags: [],
defValue: "",
enabled: true,
allTenants: false,
files: [],
@ -104,6 +108,55 @@ class PlatformCreate extends Component {
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})
}
/**
* Remove the selected property from the property list.
* */
@ -161,6 +214,10 @@ class PlatformCreate extends Component {
};
_onCreatePlatform() {
//Call the platform create api.
let platform = {};
}
@ -193,6 +250,8 @@ class PlatformCreate extends Component {
selectedProperty,
propertyTypes,
name,
tags,
defValue,
description,
property} = this.state;
@ -236,6 +295,19 @@ class PlatformCreate extends Component {
onToggle={this._handleToggle.bind(this)}
toggled={enabled}
/> <br/>
<TextField
id="tags"
hintText="Enter Platform tags.."
floatingLabelText="Tags*"
floatingLabelFixed={true}
value={defValue}
onChange={this._handleTagChange.bind(this)}
onKeyPress={this._addTags.bind(this)}
/><br/>
<div style={this.styles.wrapper}>
{tags.map(this._renderChip, this)}
</div>
<br/>
<div>
<p className="createplatformproperties">Platform Properties</p>
<div id="property-container">

@ -97,8 +97,8 @@ class PlatformListing extends Component {
handleRowClick={this._onRowClick.bind(this)}
noDataMessage={{type: 'button', text: 'Create Platform'}}/>
</Card>
</div>);
</div>
);
}
}

@ -20,10 +20,10 @@ import qs from 'qs';
import PropTypes from 'prop-types';
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 RaisedButton from 'material-ui/RaisedButton';
import {Card, CardActions, CardTitle} from 'material-ui/Card';
import {TextValidator, ValidatorForm} from 'react-material-ui-form-validator';
//todo: remove the {TextValidator, ValidatorForm} and implement it manually.
@ -40,36 +40,43 @@ class Login extends Component {
constructor() {
super();
this.state = {
isLoggedIn: true,
isLoggedIn: false,
referrer: "/",
userName: "",
password: "",
rememberMe: true
rememberMe: true,
errors: {}
}
}
componentWillMount() {
console.log("IN Login")
}
componentDidMount() {
let queryString = this.props.location.search;
console.log(queryString);
queryString = queryString.replace(/^\?/, '');
/* With QS version up we can directly use {ignoreQueryPrefix: true} option */
let params = qs.parse(queryString);
if (params.referrer) {
this.setState({referrer: params.referrer});
}
console.log("in Login")
// let queryString = this.props.location.search;
// console.log(queryString);
// queryString = queryString.replace(/^\?/, '');
// /* With QS version up we can directly use {ignoreQueryPrefix: true} option */
// let params = qs.parse(queryString);
// if (params.referrer) {
// this.setState({referrer: params.referrer});
// }
}
handleLogin(event) {
_handleLogin(event) {
event.preventDefault();
this._validateForm();
}
/**
* Handles the username field change event.
* */
onUserNameChange(event) {
_onUserNameChange(event, value) {
this.setState(
{
userName: event.target.value
userName: value
}
);
}
@ -77,10 +84,10 @@ class Login extends Component {
/**
* Handles the password field change event.
* */
onPasswordChange(event) {
_onPasswordChange(event, value) {
this.setState(
{
password: event.target.value
password: value
}
);
}
@ -88,7 +95,7 @@ class Login extends Component {
/**
* Handles the remember me check.
* */
handleRememberMe() {
_handleRememberMe() {
this.setState(
{
rememberMe: !this.state.rememberMe
@ -96,6 +103,22 @@ class Login extends Component {
);
}
/**
* Validate the login form.
* */
_validateForm() {
let errors = {};
if (!this.state.password) {
errors["passwordError"] = "Password is Required";
}
if (!this.state.userName) {
errors["userNameError"] = "User Name is Required";
}
this.setState({errors: errors}, console.log(errors));
}
render() {
if (!this.state.isLoggedIn) {
@ -107,37 +130,32 @@ class Login extends Component {
<Card>
<CardTitle title="WSO2 IoT App Publisher"/>
<CardActions>
<ValidatorForm
ref="form"
onSubmit={this.handleLogin.bind(this)}
onError={errors => console.log(errors)}>
<TextValidator
floatingLabelText="User Name"
<form onSubmit={this._handleLogin.bind(this)}>
<TextField
hintText="Enter the User Name."
id="username"
errorText={this.state.errors["userNameError"]}
floatingLabelText="User Name*"
floatingLabelFixed={true}
onChange={this.onUserNameChange.bind(this)}
name="userName"
validators={['required']}
errorMessages={['User Name is required']}
value={this.state.userName}
/>
<br/>
<TextValidator
floatingLabelText="Password"
floatingLabelFixed={true}
onChange={this.onPasswordChange.bind(this)}
name="password"
onChange={this._onUserNameChange.bind(this)}
/><br/>
<TextField
hintText="Enter the Password."
id="password"
type="password"
errorText={this.state.errors["passwordError"]}
floatingLabelText="Password*"
floatingLabelFixed={true}
value={this.state.password}
validators={['required']}
errorMessages={['Password is required']}
/>
<br/>
onChange={this._onPasswordChange.bind(this)}
/><br/>
<Checkbox label="Remember me."
onCheck={this.handleRememberMe.bind(this)}
onCheck={this._handleRememberMe.bind(this)}
checked={this.state.rememberMe}/>
<br/>
<RaisedButton type="submit" label="Login"/>
</ValidatorForm>
</form>
</CardActions>
</Card>
</div>);

Loading…
Cancel
Save