Authentication handling initial impl and code formatting according to https://github.com/airbnb/javascript/tree/master/react#basic-rules.

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

@ -18,6 +18,7 @@
import './App.scss'; import './App.scss';
import React, {Component} from 'react'; import React, {Component} from 'react';
import AuthHandler from './api/authHandler';
import createHistory from 'history/createBrowserHistory'; import createHistory from 'history/createBrowserHistory';
import {BrowserRouter as Router, Redirect, Route, Switch} from 'react-router-dom' 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';
@ -54,12 +55,19 @@ class Base extends Component {
constructor() { constructor() {
super(); super();
this.state = { this.state = {
user: "s" user: null
} }
} }
componentWillMount() { componentWillMount() {
let user = AuthHandler.getUser();
if (user) {
if (!AuthHandler.isTokenExpired()) {
this.setState({user: user});
}
}
} }
componentDidMount() { componentDidMount() {
@ -67,7 +75,7 @@ class Base extends Component {
} }
render() { render() {
if (this.state.user) { if (this.state.user !== null) {
console.log("Have User."); console.log("Have User.");
return ( return (
<div className="container"> <div className="container">

@ -1,45 +0,0 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
'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() {
}
}

@ -1,120 +0,0 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
'use strict';
import Helper from './helpers/AppMgtApiHelpers';
/**
* 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,106 @@
/*
* 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';
import Axios from 'axios';
import User from './data/user';
import Utils from './data/utils';
import Constants from "../common/constants";
/**
* Handles all tasks related to Authentication and Authorization.
* Generate access tokens, verify the user has necessary permissions etc.
* */
class AuthHandler {
/**
* Sends a request to the auth handler endpoint (auth/application-mgt/v1.0/auth/login) and generate token pair.
* @param userName: The user name of the user.
* @param password: The user password.
* @return Object: The response object from the axios post.
* */
static login(userName, password) {
const headers = {"Content-type": "application/json"};
let login_promise = Axios.post("https://localhost:9443/auth/application-mgt/v1.0/auth/login?userName=admin&password=admin",
null, {headers: headers});
login_promise.then(response => {
console.log(response);
const userName = response.data.userName;
const validityPeriod = response.data.expires_in; // In seconds
const WSO2_IOT_TOKEN = response.data.access_token;
const refreshToken = response.data.refresh_token;
const clientId = response.data.application_info[0].consumerKey;
const clientSecret = response.data.application_info[0].consumerSecret;
const user = new User(userName, clientId, clientSecret, validityPeriod);
console.log(user);
user.setAuthToken(WSO2_IOT_TOKEN, validityPeriod);
AuthHandler.setUser(user);
}
);
return login_promise;
};
/**
* Persists the user object in browser's local storage.
* @param user: The user object.
* */
static setUser(user) {
if (!user instanceof User) {
throw "Invalid user object";
}
localStorage.setItem(Constants.userConstants.WSO2_USER, JSON.stringify(user.toJson()));
/* TODO: IMHO it's better to get this key (`wso2_user`) from configs */
}
/**
* Get the logged in user.
* @return User: The logged in user object.
* */
static getUser() {
const userData = localStorage.getItem(Constants.userConstants.WSO2_USER);
const partialToken = Utils.getCookie(Constants.userConstants.PARTIAL_TOKEN);
if (!(userData && partialToken)) {
return null;
}
return User.fromJson(JSON.parse(userData));
}
isLoggedIn() {
}
logout() {
}
/**
* Checks whether the access token is expired.
* @return boolean: True if expired. False otherwise.
* */
static isTokenExpired() {
const userData = AuthHandler.getUser().getAuthToken();
return (Date.now() - userData._createdTime) > userData._expires;
}
}
export default AuthHandler;

@ -0,0 +1,112 @@
/*
* 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";
import Utils from './utils'
import Constants from '../../common/constants';
/**
* Represent an user logged in to the application, There will be allays one user per session and
* this user details will be persist in browser localstorage.
*/
export default class User {
constructor(name, clientId, clientSecret, validityPeriod) {
if (User._instance) {
return User._instance;
}
this._userName = name;
this._clientId = clientId;
this._clientSecret = clientSecret;
this._expires = validityPeriod;
this._createdTime = Date.now();
User._instance = this;
}
/**
* OAuth scopes which are available for use by this user
* @returns {Array} : An array of scopes
*/
get scopes() {
return this._scopes;
}
/**
* Set OAuth scopes available to be used by this user
* @param {Array} newScopes : An array of scopes
*/
set scopes(newScopes) {
Object.assign(this.scopes, newScopes);
}
/**
* Get the JS accessible access token fragment from cookie storage.
* @returns {String|null}
*/
getAuthToken() {
return Utils.getCookie(Constants.userConstants.PARTIAL_TOKEN);
}
/**
* Store the JavaScript accessible access token segment in cookie storage
* @param {String} newToken : Part of the access token which needs when accessing REST API
* @param {Number} validityPeriod : Validity period of the cookie in seconds
*/
setAuthToken(newToken, validityPeriod) {
Utils.delete_cookie(Constants.userConstants.PARTIAL_TOKEN);
Utils.setCookie(Constants.userConstants.PARTIAL_TOKEN, newToken, validityPeriod);
}
/**
*
* @param type
*/
checkPermission(type) {
throw ("Not implemented!");
}
/**
* Provide user data in JSON structure.
* @returns {JSON} : JSON representation of the user object
*/
toJson() {
return {
name: this._userName,
clientId: this._clientId,
clientSecret: this._clientSecret,
expires: this._expires
};
}
/**
* User utility method to create an user from JSON object.
* @param {JSON} userJson : Need to provide user information in JSON structure to create an user object
* @returns {User} : An instance of User(this) class.
*/
static fromJson(userJson) {
const _user = new User(userJson.name);
_user._clientId = userJson.clientId;
_user._clientSecret = userJson.clientSecret;
_user._expires = userJson.expires;
console.log(_user);
return _user;
}
}
User._instance = null; // A private class variable to preserve the single instance of a swaggerClient

@ -0,0 +1,94 @@
/*
* 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.
*/
/**
* Utility class for Publisher application
*/
class PublisherUtils {
/**
* TODO: Remove this method one the initial phase is done, This is used to continue the API class until the login page is create
* @returns {promise}
*/
// static autoLogin() {
// let auth = new AuthManager();
// return auth.authenticateUser('admin', 'admin');
// }
/**
* Get JavaScript accessible cookies saved in browser, by giving the cooke name.
* @param {String} name : Name of the cookie which need to be retrived
* @returns {String|null} : If found a cookie with given name , return its value,Else null value is returned
*/
static getCookie(name) {
let pairs = document.cookie.split(";");
let cookie = null;
for (let pair of pairs) {
pair = pair.split("=");
let cookie_name = pair[0].trim();
let value = encodeURIComponent(pair[1]);
if (cookie_name === name) {
cookie = value;
break;
}
}
return cookie;
}
/**
* Delete a browser cookie given its name
* @param {String} name : Name of the cookie which need to be deleted
*/
static delete_cookie(name) {
document.cookie = name + '=; Path=' + "/" + '; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
}
/**
* Set a cookie with given name and value assigned to it. Cookies can be only set to the same origin,
* which the script is running
* @param {String} name : Name of the cookie which need to be set
* @param {String} value : Value of the cookie, expect it to be URLEncoded
* @param {number} validityPeriod : (Optional) Validity period of the cookie in seconds
* @param {String} path : Path which needs to set the given cookie
* @param {boolean} secured : secured parameter is set
*/
static setCookie(name, value, validityPeriod, path = "/", secured = true) {
let expires = "";
const securedDirective = secured ? "; Secure" : "";
if (validityPeriod) {
const date = new Date();
date.setTime(date.getTime() + validityPeriod * 1000);
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + value + expires + "; path=" + path + securedDirective + validityPeriod
}
/**
* Given an object returns whether the object is empty or not
* @param {Object} object : Any JSON object
* @returns {boolean}
*/
static isEmptyObject(object) {
return Object.keys(object).length === 0 && object.constructor === Object
}
}
export default PublisherUtils;

@ -0,0 +1,183 @@
/*
* 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';
import Axios from 'axios';
import AuthHandler from './authHandler';
import Constants from '../common/constants';
import Helper from './helpers/appMgtApiHelpers';
export default class Endpoint {
/* =================================================================
* Application related apis
* */
/**
* 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 applicationData, the proper application object will be created and send it to the api.
* */
static createApplication(applicationData) {
let app = Helper.buildApplication(applicationData).application;
let user = AuthHandler.getUser();
console.log(user.idToken);
const headers = {
"Authorization": 'Bearer ' + user.getAuthToken(),
"Content-Type": "application/json",
};
Axios.post(Constants.appManagerEndpoints.CREATE_APP, app, {headers: headers}).then(
function (response) {
console.log(response);
}
).catch(function (err) {
console.log(err);
});
}
/**
* Method to handle application release process.
* */
static releaseApplication() {
}
/**
* Promote the current state of the application.
* @param appId: The uuid of the application which the state should be updated.
* */
static updateState(appId) {
}
/**
* Get the next possible state, which the application can be promoted to.
* @param appId: The application uuid.
*/
static getNextState(appId) {
}
/**
* Edit created application.
* @param applicationData: The modified application data.
* */
static editApplication(applicationData) {
}
/**
* Get all the created applications for the user.
* @return Object: The response object from the axios post.
* */
static getApplications() {
let user = AuthHandler.getUser();
console.log("Get all applications", user.getAuthToken());
const headers = {
"Authorization": 'Bearer ' + user.getAuthToken(),
'Accept': 'application/json',
"Content-Type": "application/json",
};
return Axios.get(Constants.appManagerEndpoints.GET_ALL_APPS, {headers: headers});
}
/**
* 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) {
}
/*
* End of Application management apis.
* =================================================================
* */
/*
* =================================================================
* Platform related apis
* */
/**
* Create a new Platform
* @param platformData: The platform data object.
* */
static createPlatform(platformData) {
const headers = {
"Authorization": 'Bearer ' + AuthHandler.getUser().getAuthToken(),
'Accept': 'application/json',
"Content-Type": "application/json",
};
Axios.post(Constants.platformManagerEndpoints.CREATE_PLATFORM, platformData, {headers: headers}).then(
function (response) {
console.log(response);
}
).catch(function (err) {
console.log(err);
});
}
/**
* 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) {
}
/*
* End of Platform management apis.
* =================================================================
* */
}

@ -26,24 +26,31 @@ export default class Helper {
/** /**
* Generate application object from form data passed. * Generate application object from form data passed.
* @param appData: Application data from the application creation form. * @param appData: Application data from the application creation form.
* @return {Object, Object}: The application object and the set of images related to the application.
* */ * */
static buildApplication(appData) { static buildApplication(appData) {
let application = {}; let application = {};
let images = {}; let images = {};
for (var step in appData) { for (let step in appData) {
let tmpData = appData[step].data.step; let tmpData = appData[step].data.step;
for (var prop in tmpData) { for (let prop in tmpData) {
if (prop === 'banner' || prop === 'screenshots' || prop === 'icon') { if (prop === 'banner' || prop === 'screenshots' || prop === 'icon') {
images[prop] = tmpData[prop]; images[prop] = tmpData[prop];
} else if(prop === 'tags') {
let tags = [];
let tagsFromStep = tmpData[prop];
for (let tag in tagsFromStep) {
console.log(tag);
tags.push(tagsFromStep[tag].value);
}
application[prop] = tags;
} else { } else {
application[prop] = tmpData[prop]; application[prop] = tmpData[prop];
} }
} }
} }
return {application, images};
console.log(application, images);
} }
}
}

@ -16,16 +16,30 @@
* under the License. * under the License.
*/ */
scopes = 'perm:application:get perm:application:create perm:application:update perm:application-mgt:login' + export default class Constants {
' perm:application:delete perm:platform:add perm:platform:remove perm:roles:view perm:devices:view';
TOKEN_ENDPOINT = '/token'; static scopes = 'perm:application:get perm:application:create perm:application:update perm:application-mgt:login' +
DYNAMIC_CLIENT_REGISTER_ENDPOINT = '/api-application-registration/register'; ' perm:application:delete perm:platform:add perm:platform:remove perm:roles:view perm:devices:view';
static TOKEN_ENDPOINT = '/token';
static DYNAMIC_CLIENT_REGISTER_ENDPOINT = '/api-application-registration/register';
static appManagerEndpoints = {
GET_ALL_APPS: 'https://localhost:8243/api/application-mgt/v1.0/applications/1.0.0/',
CREATE_APP: 'https://localhost:8243/api/application-mgt/v1.0/applications/1.0.0/',
UPLOAD_IMAGES: '/api/application-mgt/v1.0/applications/1.0.0/upload-image-artifacts/', //+appId
};
static platformManagerEndpoints = {
CREATE_PLATFORM: 'https://localhost:8243/api/application-mgt/v1.0/platforms/1.0.0/'
}
static userConstants = {
WSO2_USER: 'wso2_user',
PARTIAL_TOKEN: 'WSO2_IOT_TOKEN'
}
}
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,7 +18,7 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import Dialog from 'material-ui/Dialog'; import Dialog from 'material-ui/Dialog';
import Endpoint from '../../api/Endpoints'; import Endpoint from '../../api/endpoints';
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 {Step1, Step2, Step3} from './CreateSteps'; import {Step1, Step2, Step3} from './CreateSteps';
@ -67,7 +67,7 @@ class ApplicationCreate extends Component {
/** /**
* Handles next button click event. * Handles next button click event.
* */ * */
handleNext = () => { handleNext() {
console.log("Handle Next"); console.log("Handle Next");
const {stepIndex} = this.state; const {stepIndex} = this.state;
this.setState({ this.setState({
@ -79,7 +79,7 @@ class ApplicationCreate extends Component {
/** /**
* Handles form submit. * Handles form submit.
* */ * */
handleSubmit = () => { handleSubmit() {
console.log(this.state.stepData); console.log(this.state.stepData);
Endpoint.createApplication(this.state.stepData); Endpoint.createApplication(this.state.stepData);
@ -89,7 +89,7 @@ class ApplicationCreate extends Component {
* Handles cancel button click event. * Handles cancel button click event.
* This will show a confirmation dialog to cancel the application creation process. * This will show a confirmation dialog to cancel the application creation process.
* */ * */
handleCancel = () => { handleCancel() {
this.setState({isDialogOpen: true}); this.setState({isDialogOpen: true});
}; };
@ -97,7 +97,7 @@ class ApplicationCreate extends Component {
* Handled [ < Prev ] button click. * Handled [ < Prev ] button click.
* This clears the data in the current step and returns to the previous step. * This clears the data in the current step and returns to the previous step.
* */ * */
handlePrev = () => { handlePrev() {
const {stepIndex} = this.state; const {stepIndex} = this.state;
if (stepIndex > 0) { if (stepIndex > 0) {
this.removeStepData(); this.removeStepData();
@ -108,7 +108,7 @@ class ApplicationCreate extends Component {
/** /**
* Saves form data in each step in to the state. * Saves form data in each step in to the state.
* */ * */
setStepData = (step, data) => { setStepData(step, data) {
console.log(step, data, this.state.stepData); console.log(step, data, this.state.stepData);
let tmpStepData = this.state.stepData; let tmpStepData = this.state.stepData;
tmpStepData.push({step: step, data: data}); tmpStepData.push({step: step, data: data});
@ -119,7 +119,7 @@ class ApplicationCreate extends Component {
/** /**
* Remove the last data point * Remove the last data point
* */ * */
removeStepData = () => { removeStepData() {
let tempData = this.state.stepData; let tempData = this.state.stepData;
tempData.pop(); tempData.pop();
this.setState({stepData: tempData}); this.setState({stepData: tempData});
@ -129,7 +129,7 @@ class ApplicationCreate extends Component {
* 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.
* */ * */
handleYes = () => { handleYes() {
this.setState({finished: false, stepIndex: 0, stepData: [], isDialogOpen: false}); this.setState({finished: false, stepIndex: 0, stepData: [], isDialogOpen: false});
}; };
@ -137,7 +137,7 @@ class ApplicationCreate extends Component {
* Handles No button in app creation cancellation dialog. * Handles No button in app creation cancellation dialog.
* Returns to the same step. * Returns to the same step.
* */ * */
handleNo = () => { handleNo() {
this.setState({isDialogOpen: false}); this.setState({isDialogOpen: false});
}; };
@ -153,21 +153,27 @@ class ApplicationCreate extends Component {
getStepContent(stepIndex) { getStepContent(stepIndex) {
switch (stepIndex) { switch (stepIndex) {
case 0: case 0:
return <Step1 handleNext={this.handleNext} return <Step1
setData={this.setStepData} handleNext={this.handleNext}
removeData={this.removeStepData}/>; setData={this.setStepData}
removeData={this.removeStepData}
/>;
case 1: case 1:
return <Step2 handleNext={this.handleNext} return <Step2
handlePrev={this.handlePrev} handleNext={this.handleNext}
setData={this.setStepData} handlePrev={this.handlePrev}
removeData={this.removeStepData}/>; setData={this.setStepData}
removeData={this.removeStepData}
/>;
case 2: case 2:
return <Step3 handleFinish={this.handleNext} return <Step3
handlePrev={this.handlePrev} handleFinish={this.handleNext}
setData={this.setStepData} handlePrev={this.handlePrev}
removeData={this.removeStepData}/>; setData={this.setStepData}
removeData={this.removeStepData}
/>;
default: default:
return <div></div>; return <div/>;
} }
} }

@ -17,6 +17,7 @@
*/ */
import React, {Component} from 'react'; import React, {Component} from 'react';
import EndPoint from '../../api/endpoints';
import {withRouter} from 'react-router-dom'; import {withRouter} from 'react-router-dom';
import TextField from 'material-ui/TextField'; import TextField from 'material-ui/TextField';
import DataTable from '../UIComponents/DataTable'; import DataTable from '../UIComponents/DataTable';
@ -44,37 +45,37 @@ class ApplicationListing extends Component {
data = [ data = [
{ {
id: Math.random(), id: Math.random(),
applicationName:"Cne", applicationName: "Cne",
platform:'Android', platform: 'Android',
category:"Public", category: "Public",
status: "Created" status: "Created"
}, },
{ {
id: Math.random(), id: Math.random(),
applicationName:"Gone", applicationName: "Gone",
platform:'IOS', platform: 'IOS',
category:"Public", category: "Public",
status: "Created" status: "Created"
}, },
{ {
id: Math.random(), id: Math.random(),
applicationName:"Ane", applicationName: "Ane",
platform:'Android', platform: 'Android',
category:"Public", category: "Public",
status: "Created" status: "Created"
}, },
{ {
id: Math.random(), id: Math.random(),
applicationName:"one", applicationName: "one",
platform:'Android', platform: 'Android',
category:"Public", category: "Public",
status: "Created" status: "Created"
}, },
{ {
id: Math.random(), id: Math.random(),
applicationName:"one", applicationName: "one",
platform:'Android', platform: 'Android',
category:"Public", category: "Public",
status: "Created" status: "Created"
}, },
]; ];
@ -84,19 +85,21 @@ class ApplicationListing extends Component {
data_id: "image", data_id: "image",
data_type: "image", data_type: "image",
sortable: false, sortable: false,
label: ""}, label: ""
},
{ {
data_id: "applicationName", data_id: "applicationName",
data_type: "string", data_type: "string",
sortable: true, sortable: true,
label: "Application Name", label: "Application Name",
sort: this._sortData.bind(this) sort: this.sortData.bind(this)
}, },
{ {
data_id: "platform", data_id: "platform",
data_type: "image_array", data_type: "image_array",
sortable: false, sortable: false,
label: "Platform"}, label: "Platform"
},
{ {
data_id: "category", data_id: "category",
data_type: "string", data_type: "string",
@ -125,36 +128,41 @@ class ApplicationListing extends Component {
Theme.removeThemingScripts(this.scriptId); Theme.removeThemingScripts(this.scriptId);
} }
componentDidMount() {
let getApps = EndPoint.getApplications();
getApps.then(response => {
console.log(response);
})
}
/** /**
* Handles the search action. * Handles the search action.
* When typing in the search bar, this method will be invoked. * When typing in the search bar, this method will be invoked.
* */ * */
_searchApplications(event, word) { searchApplications(event, word) {
let searchedData; let searchedData;
if (word){ if (word) {
searchedData = this.data.filter((dataItem) => { searchedData = this.data.filter((dataItem) => {
return dataItem.applicationName.includes(word); return dataItem.applicationName.includes(word);
}); });
} else { } else {
searchedData = this.data; searchedData = this.data;
} }
this.setState({data: searchedData}, console.log("Searched data ", this.state.data)); this.setState({data: searchedData}, console.log("Searched data ", this.state.data));
} }
/** /**
* Handles sort data function and toggles the asc state. * Handles sort data function and toggles the asc state.
* asc: true : sort in ascending order. * asc: true : sort in ascending order.
* */ * */
_sortData() { sortData() {
let isAsc = this.state.asc; let isAsc = this.state.asc;
let datas = isAsc?this.data.sort(this._compare):this.data.reverse(); let datas = isAsc ? this.data.sort(this.compare) : this.data.reverse();
this.setState({data: datas, asc: !isAsc}); this.setState({data: datas, asc: !isAsc});
} }
_compare(a, b) { compare(a, b) {
if (a.applicationName < b.applicationName) if (a.applicationName < b.applicationName)
return -1; return -1;
if (a.applicationName > b.applicationName) if (a.applicationName > b.applicationName)
@ -162,8 +170,8 @@ class ApplicationListing extends Component {
return 0; return 0;
} }
_onRowClick(id) { onRowClick(id) {
this.props.history.push("apps/"+id); this.props.history.push("apps/" + id);
} }
render() { render() {
@ -171,18 +179,17 @@ class ApplicationListing extends Component {
<div className="middle applicationListingMiddle"> <div className="middle applicationListingMiddle">
<Card className="applicationListingCard"> <Card className="applicationListingCard">
<TextField hintText="Search" className="applicationListingSearch" <TextField hintText="Search" className="applicationListingSearch"
onChange={this._searchApplications.bind(this)}/> onChange={this.searchApplications.bind(this)}/>
<CardTitle title="Applications" className="applicationListTitle"/> <CardTitle title="Applications" className="applicationListTitle"/>
<CardActions> <DataTable
headers={this.headers}
</CardActions> data={this.state.data}
<DataTable headers={this.headers} handleRowClick={this.onRowClick.bind(this)}
data={this.state.data} noDataMessage={{type: 'button', text: 'Create Application'}}
handleRowClick={this._onRowClick.bind(this)} />
noDataMessage={{type: 'button', text: 'Create Application'}}/>
</Card> </Card>
</div>
</div>); );
} }
} }

@ -39,11 +39,13 @@ import Theme from '../../../theme';
class Step1 extends Component { class Step1 extends Component {
constructor() { constructor() {
super(); super();
this.platforms = [{identifier: 1}, {identifier: 2}, {identifier: 3}];
this.stores = [{identifier: 5}, {identifier: 2}, {identifier: 3}];
this.state = { this.state = {
finished: false, finished: false,
stepIndex: 0, stepIndex: 0,
store: 1, store: 1,
platform: 1, platform: 0,
stepData: [], stepData: [],
title: "", title: "",
titleError: "" titleError: ""
@ -65,17 +67,17 @@ class Step1 extends Component {
/** /**
* Invokes the handleNext function in Create component. * Invokes the handleNext function in Create component.
* */ * */
_handleNext = () => { handleNext() {
this.props.handleNext(); this.props.handleNext();
}; };
/** /**
* Persist the current form data to the state. * Persist the current form data to the state.
* */ * */
_setStepData() { setStepData() {
var step = { let step = {
store: this.state.store, store: this.state.store,
platform: this.state.platform platform: this.platforms[this.state.platform]
}; };
this.props.setData("step1", {step: step}); this.props.setData("step1", {step: step});
} }
@ -86,14 +88,14 @@ class Step1 extends Component {
* Sets the data to the state. * Sets the data to the state.
* Invokes the handleNext method of Create component. * Invokes the handleNext method of Create component.
* */ * */
_handleClick() { handleClick() {
this._setStepData(); this.setStepData();
} }
/** /**
* Triggers when changing the Platform selection. * Triggers when changing the Platform selection.
* */ * */
_onChangePlatform = (event, index, value) => { onChangePlatform(event, index, value) {
console.log(value); console.log(value);
this.setState({platform: value}); this.setState({platform: value});
}; };
@ -101,17 +103,10 @@ class Step1 extends Component {
/** /**
* Triggers when changing the Store selection. * Triggers when changing the Store selection.
* */ * */
_onChangeStore = (event, index, value) => { onChangeStore(event, index, value) {
this.setState({store: value}); this.setState({store: value});
}; };
/**
* Triggers when user types on Title text field.
* */
_onChangeTitle = (event, value) => {
this.setState({title: value});
};
render() { render() {
return ( return (
<div> <div>
@ -122,30 +117,30 @@ class Step1 extends Component {
floatingLabelText="Store Type*" floatingLabelText="Store Type*"
value={this.state.store} value={this.state.store}
floatingLabelFixed={true} floatingLabelFixed={true}
onChange={this._onChangeStore.bind(this)} onChange={this.onChangeStore.bind(this)}
> >
<MenuItem value={1} primaryText="Enterprise"/> <MenuItem value={0} primaryText="Enterprise"/>
<MenuItem value={2} primaryText="Public"/> <MenuItem value={1} primaryText="Public"/>
</SelectField> <br/> </SelectField>
<br/>
<SelectField <SelectField
floatingLabelText="Platform*" floatingLabelText="Platform*"
value={this.state.platform} value={this.state.platform}
floatingLabelFixed={true} floatingLabelFixed={true}
onChange={this._onChangePlatform.bind(this)} onChange={this.onChangePlatform.bind(this)}
> >
<MenuItem value={1} primaryText="Android"/> <MenuItem value={0} primaryText="Android"/>
<MenuItem value={2} primaryText="iOS"/> <MenuItem value={1} primaryText="iOS"/>
<MenuItem value={{name: "Web", id:3}} primaryText="Web"/> <MenuItem value={2} primaryText="Web"/>
</SelectField> </SelectField>
</div> </div>
<br/> <br/>
<br/> <br/>
<div className="nextButton"> <div className="nextButton">
<RaisedButton <RaisedButton
label="Next >" label="Next >"
primary={true} primary={true}
onClick={this._handleClick.bind(this)} onClick={this.handleClick.bind(this)}
/> />
</div> </div>
</div> </div>

@ -65,6 +65,7 @@ class Step2 extends Component {
visibility: 0, visibility: 0,
description: "", description: "",
screenshots: [], screenshots: [],
identifier: "",
shortDescription: "" shortDescription: ""
}; };
this.scriptId = "application-create-step2"; this.scriptId = "application-create-step2";
@ -86,19 +87,19 @@ class Step2 extends Component {
* Clears the tags text field. * Clears the tags text field.
* Chip gets two parameters: Key and value. * Chip gets two parameters: Key and value.
* */ * */
_addTags(event) { addTags(event) {
let tags = this.state.tags; let tags = this.state.tags;
if (event.charCode === 13) { if (event.charCode === 13) {
event.preventDefault(); event.preventDefault();
tags.push({key: Math.floor(Math.random() * 1000), value: event.target.value}); tags.push({key: Math.floor(Math.random() * 1000), value: event.target.value});
this.setState({tags, defValue: ""}); this.setState({tags, defValue: ""}, console.log(tags));
} }
} }
/** /**
* Set the value for tag. * Set the value for tag.
* */ * */
_handleTagChange(event) { handleTagChange(event) {
let defaultValue = this.state.defValue; let defaultValue = this.state.defValue;
defaultValue = event.target.value; defaultValue = event.target.value;
this.setState({defValue: defaultValue}) this.setState({defValue: defaultValue})
@ -107,21 +108,21 @@ class Step2 extends Component {
/** /**
* Invokes the handleNext function in Create component. * Invokes the handleNext function in Create component.
* */ * */
_handleNext() { handleNext() {
let fields = [{name: "Title", value: this.state.title}, let fields = [{name: "Title", value: this.state.title},
{name: "Short Description", value: this.state.shortDescription}, {name: "Short Description", value: this.state.shortDescription},
{name: "Description", value: this.state.description}, {name: "Description", value: this.state.description},
{name: "Banner", value: this.state.banner}, {name: "Banner", value: this.state.banner},
{name: "Screenshots", value: this.state.screenshots}, {name: "Screenshots", value: this.state.screenshots},
{name: "Identifier", value: this.state.identifier},
{name: "Icon", value: this.state.icon}]; {name: "Icon", value: this.state.icon}];
this._validate(fields); this.validate(fields);
// this.props.handleNext();
} }
/** /**
* Invokes the handlePrev function in Create component. * Invokes the handlePrev function in Create component.
* */ * */
_handlePrev() { handlePrev() {
this.props.handlePrev(); this.props.handlePrev();
} }
@ -129,7 +130,7 @@ 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(key) {
this.chipData = this.state.tags; this.chipData = this.state.tags;
const chipToDelete = this.chipData.map((chip) => chip.key).indexOf(key); const chipToDelete = this.chipData.map((chip) => chip.key).indexOf(key);
this.chipData.splice(chipToDelete, 1); this.chipData.splice(chipToDelete, 1);
@ -139,18 +140,18 @@ class Step2 extends Component {
/** /**
* Creates Chip array from state.tags. * Creates Chip array from state.tags.
* */ * */
_renderChip(data) { renderChip(data) {
return ( return (
<Chip <Chip
key={data.key} key={data.key}
onRequestDelete={() => this._handleRequestDelete(data.key)} onRequestDelete={() => this.handleRequestDelete(data.key)}
className="applicationCreateChip"> className="applicationCreateChip">
{data.value} {data.value}
</Chip> </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"/>
<MenuItem value={1} primaryText="Roles"/> <MenuItem value={1} primaryText="Roles"/>
@ -167,7 +168,7 @@ class Step2 extends Component {
/** /**
* Validate the form. * Validate the form.
* */ * */
_validate(fields) { validate(fields) {
let errors = {}; let errors = {};
let errorsPresent = false; let errorsPresent = false;
fields.forEach(function (field) { fields.forEach(function (field) {
@ -181,6 +182,15 @@ class Step2 extends Component {
} }
break; break;
} }
case 'Identifier': {
if (field.value === "") {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Short Description': { case 'Short Description': {
if (field.value === "") { if (field.value === "") {
errors[field.name] = field.name + " is required!"; errors[field.name] = field.name + " is required!";
@ -219,7 +229,7 @@ class Step2 extends Component {
} }
case 'Screenshots': { case 'Screenshots': {
if (field.value.length < 3) { if (field.value.length < 3) {
errors[field.name] = "3 " +field.name + " are required!"; errors[field.name] = "3 " + field.name + " are required!";
errorsPresent = true; errorsPresent = true;
} else { } else {
errorsPresent = false; errorsPresent = false;
@ -229,41 +239,40 @@ class Step2 extends Component {
} }
}); });
console.log(errorsPresent);
if (!errorsPresent) { if (!errorsPresent) {
this._setStepData(); this.setStepData();
} else { } else {
this.setState({errors: errors}, console.log(errors)); this.setState({errors: errors}, console.log(errors));
} }
} }
/** /**
* 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 = { let stepData = {
tags: this.state.tags,
icon: this.state.icon, icon: this.state.icon,
title: this.state.title, name: this.state.name,
tags: this.state.tags,
banner: this.state.banner, banner: this.state.banner,
category: this.state.category, category: this.categories[this.state.category],
identifier: this.state.identifier,
screenshots: this.state.screenshots, screenshots: this.state.screenshots,
description: this.state.description, description: this.state.description,
shortDescription: this.state.shortDescription shortDescription: this.state.shortDescription
}; };
this.props.setData("step2", {step: stepData}); this.props.setData("step2", {step: stepData});
} };
/** /**
* Set text field values to state. * Set text field values to state.
* */ * */
_onTextFieldChange(event, value) { onTextFieldChange(event, value) {
let field = event.target.id; let field = event.target.id;
switch (field) { switch (field) {
case "title": { case "name": {
this.setState({title: value}); this.setState({name: value});
break; break;
} }
case "shortDescription": { case "shortDescription": {
@ -274,30 +283,34 @@ class Step2 extends Component {
this.setState({description: value}); this.setState({description: value});
break; break;
} }
case "identifier": {
this.setState({identifier: value});
break;
}
} }
} };
/** /**
* Removed user uploaded banner. * Removed user uploaded banner.
* */ * */
_removeBanner(event, d) { removeBanner(event, d) {
console.log(event, d); console.log(event, d);
this.setState({banner: []}); this.setState({banner: []});
} };
/** /**
* Removes uploaded icon. * Removes uploaded icon.
* */ * */
_removeIcon(event) { removeIcon(event) {
this.setState({icon: []}); this.setState({icon: []});
} };
/** /**
* Removes selected screenshot. * Removes selected screenshot.
* */ * */
_removeScreenshot(event) { removeScreenshot(event) {
console.log(event.target) console.log(event.target)
} };
render() { render() {
console.log(this.state.visibilityComponent); console.log(this.state.visibilityComponent);
@ -306,13 +319,23 @@ class Step2 extends Component {
<div> <div>
<div> <div>
<TextField <TextField
id="title" id="name"
hintText="Enter a title for your application." hintText="Enter a name for your application."
errorText={this.state.errors["Title"]} errorText={this.state.errors["Title"]}
floatingLabelText="Title*" floatingLabelText="Name*"
floatingLabelFixed={true}
onChange={this.onTextFieldChange.bind(this)}
/>
<br/>
<TextField
id="identifier"
hintText="Unique Identifier for Application."
errorText={this.state.errors["Identifier"]}
floatingLabelText="Identifier*"
floatingLabelFixed={true} floatingLabelFixed={true}
onChange={this._onTextFieldChange.bind(this)} onChange={this.onTextFieldChange.bind(this)}
/><br/> />
<br/>
<TextField <TextField
id="shortDescription" id="shortDescription"
hintText="Enter a short description for your application." hintText="Enter a short description for your application."
@ -321,9 +344,9 @@ class Step2 extends Component {
floatingLabelFixed={true} floatingLabelFixed={true}
multiLine={true} multiLine={true}
rows={2} rows={2}
onChange={this._onTextFieldChange.bind(this)} onChange={this.onTextFieldChange.bind(this)}
/>
/><br/> <br/>
<TextField <TextField
id="description" id="description"
errorText={this.state.errors["Description"]} errorText={this.state.errors["Description"]}
@ -332,18 +355,20 @@ class Step2 extends Component {
floatingLabelFixed={true} floatingLabelFixed={true}
multiLine={true} multiLine={true}
rows={4} rows={4}
onChange={this._onTextFieldChange.bind(this)} onChange={this.onTextFieldChange.bind(this)}
/><br/> />
<br/>
<SelectField <SelectField
floatingLabelText="Visibility*" floatingLabelText="Visibility*"
value={this.state.visibility} value={this.state.visibility}
floatingLabelFixed={true} floatingLabelFixed={true}
onChange={this._onVisibilitySelect.bind(this)} onChange={this.onVisibilitySelect.bind(this)}
> >
<MenuItem value={0} primaryText="Public"/> <MenuItem value={0} primaryText="Public"/>
<MenuItem value={1} primaryText="Roles"/> <MenuItem value={1} primaryText="Roles"/>
<MenuItem value={2} primaryText="Devices"/> <MenuItem value={2} primaryText="Devices"/>
</SelectField><br/> </SelectField>
<br/>
<TextField <TextField
id="tags" id="tags"
errorText={this.state.errors["tags"]} errorText={this.state.errors["tags"]}
@ -351,11 +376,12 @@ class Step2 extends Component {
floatingLabelText="Tags*" floatingLabelText="Tags*"
floatingLabelFixed={true} floatingLabelFixed={true}
value={this.state.defValue} value={this.state.defValue}
onChange={this._handleTagChange.bind(this)} onChange={this.handleTagChange.bind(this)}
onKeyPress={this._addTags.bind(this)} onKeyPress={this.addTags.bind(this)}
/><br/> />
<div className="applicationCreateWrapper"> <br/>
{this.state.tags.map(this._renderChip, this)} <div style={this.styles.wrapper}>
{this.state.tags.map(this.renderChip, this)}
</div> </div>
<br/> <br/>
<SelectField <SelectField
@ -364,7 +390,8 @@ class Step2 extends Component {
floatingLabelFixed={true} floatingLabelFixed={true}
> >
<MenuItem value={0} primaryText="Business"/> <MenuItem value={0} primaryText="Business"/>
</SelectField> <br/> </SelectField>
<br/>
{/*Platform Specific Properties.*/} {/*Platform Specific Properties.*/}
<div className="platformSpecificPropertyDiv"> <div className="platformSpecificPropertyDiv">
<p className="platformSpecificPropertyP">Platform Specific Properties</p> <p className="platformSpecificPropertyP">Platform Specific Properties</p>
@ -375,50 +402,58 @@ class Step2 extends Component {
<p className="applicationCreateBannerTitle">Banner*:</p> <p className="applicationCreateBannerTitle">Banner*:</p>
<GridList className="applicationCreateGrid" cols={1.1}> <GridList className="applicationCreateGrid" cols={1.1}>
{this.state.banner.map((tile) => ( {this.state.banner.map((tile) => (
<GridTile key={Math.floor(Math.random() * 1000)} <GridTile
title={tile.name} key={Math.floor(Math.random() * 1000)}
actionIcon={ title={tile.name}
<IconButton onClick={this._removeBanner.bind(this)}> actionIcon={
<Clear /> <IconButton onClick={this.removeBanner.bind(this)}>
</IconButton>}> <Clear/>
<img src={tile.preview}/></GridTile> </IconButton>}>
<img src={tile.preview}/>
</GridTile>
))} ))}
{this.state.banner.length === 0 ? {this.state.banner.length === 0 ?
<Dropzone className="applicationCreateBannerDropZone" accept="image/jpeg, image/png" <Dropzone
onDrop={(banner, rejected) => { className="applicationCreateBannerDropZone"
this.setState({banner, rejected}); accept="image/jpeg, image/png"
}}> onDrop={(banner, rejected) => {
<p className="applicationCreateBannerp">+</p> this.setState({banner, rejected});
</Dropzone> : <div />} }}
>
<p className="applicationCreateBannerp">+</p>
</Dropzone> : <div/>
}
</GridList> </GridList>
</div> </div>
<br/> <br/>
<div> <div>
<p className="applicationCreateScreenshotError">{this.state.errors["Screenshots"]}</p> <p className="applicationCreateScreenshotError">{this.state.errors["Screenshots"]}</p>
<p className="applicationCreateScreenshotTitle">Screenshots*:</p> <p className="applicationCreateScreenshotTitle">Screenshots*:</p>
<GridList className = "applicationCreateScreenshotGrid" cols={1.1}> <GridList className="applicationCreateScreenshotGrid" cols={1.1}>
{this.state.screenshots.map((file) => ( {this.state.screenshots.map((file) => (
<GridTile key={Math.floor(Math.random() * 1000)} <GridTile
title={file[0].name} key={Math.floor(Math.random() * 1000)}
actionIcon={ title={file[0].name}
<IconButton onClick={this._removeScreenshot.bind(this)}> actionIcon={
<Clear/> <IconButton onClick={this.removeScreenshot.bind(this)}>
</IconButton>}> <Clear/>
</IconButton>}>
<img src={file[0].preview}/></GridTile> <img src={file[0].preview}/></GridTile>
))} ))}
{this.state.screenshots.length < 3 ? {this.state.screenshots.length < 3 ?
<Dropzone className="applicationCreateScreenshotDropZone" <Dropzone
accept="image/jpeg, image/png" className="applicationCreateScreenshotDropZone"
onDrop={(screenshots, rejected) => { accept="image/jpeg, image/png"
let tmpScreenshots = this.state.screenshots; onDrop={(screenshots, rejected) => {
tmpScreenshots.push(screenshots); let tmpScreenshots = this.state.screenshots;
this.setState({ tmpScreenshots.push(screenshots);
screenshots: tmpScreenshots}); this.setState({
}}> screenshots: tmpScreenshots
<p className="applicationCreateScreenshotp">+</p> });
</Dropzone> : <div />} }}
>
<p className="applicationCreateScreenshotp">+</p>
</Dropzone> : <div/>}
</GridList> </GridList>
</div> </div>
<br/> <br/>
@ -427,38 +462,43 @@ class Step2 extends Component {
<p className="applicationCreateIconTitle">Icon*:</p> <p className="applicationCreateIconTitle">Icon*:</p>
<GridList className="applicationCreateIconGrid" cols={1.1}> <GridList className="applicationCreateIconGrid" cols={1.1}>
{this.state.icon.map((tile) => ( {this.state.icon.map((tile) => (
<GridTile key={Math.floor(Math.random() * 1000)} <GridTile
title={tile.name} key={Math.floor(Math.random() * 1000)}
actionIcon={ title={tile.name}
<IconButton onClick={this._removeIcon.bind(this)}> actionIcon={
<Clear /> <IconButton onClick={this.removeIcon.bind(this)}>
</IconButton>}> <Clear/>
<img src={tile.preview}/></GridTile> </IconButton>}>
<img src={tile.preview}/>
</GridTile>
))} ))}
{this.state.icon.length === 0 ? {this.state.icon.length === 0 ?
<Dropzone className="applicationCreateIconDropZone" <Dropzone
accept="image/jpeg, image/png" className="applicationCreateIconDropZone"
onDrop={(icon, rejected) => {this.setState({icon, rejected});}}> accept="image/jpeg, image/png"
<p className="applicationCreateIconp">+</p> onDrop={(icon, rejected) => {
</Dropzone> : <div />} this.setState({icon, rejected});
}}
>
<p className="applicationCreateIconp">+</p>
</Dropzone> : <div/>}
</GridList> </GridList>
</div> </div>
<br/> <br/>
</div> </div>
<br/> <br/>
<br/> <br/>
<div className="applicationCreateBackAndNext"> <div className="applicationCreateBackAndNext">
<FlatButton <FlatButton
label="< Back" label="< Back"
disabled={false} disabled={false}
onClick={this._handlePrev.bind(this)} onClick={this.handlePrev.bind(this)}
className="applicationCreateBack" style={{marginRight: 12}}
/> />
<RaisedButton <RaisedButton
label="Next >" label="Next >"
primary={true} primary={true}
onClick={this._handleNext.bind(this)} onClick={this.handleNext.bind(this)}
/> />
</div> </div>
</div> </div>

@ -63,7 +63,7 @@ class Step3 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() {
@ -74,21 +74,21 @@ class Step3 extends Component {
* Handles finish button click. * Handles finish button click.
* This invokes handleNext function in parent component. * This invokes handleNext function in parent component.
* */ * */
_handleFinish() { handleFinish() {
this.props.handleFinish(); this.props.handleFinish();
} }
/** /**
* Invokes Prev button click. * Invokes Prev button click.
* */ * */
_handlePrev() { handlePrev() {
this.props.handlePrev(); this.props.handlePrev();
} }
/** /**
* Handles release application selection. * Handles release application selection.
* */ * */
_handleToggle() { handleToggle() {
let hide = this.state.showForm; let hide = this.state.showForm;
this.setState({showForm: !hide}); this.setState({showForm: !hide});
} }
@ -100,36 +100,42 @@ class Step3 extends Component {
<Toggle <Toggle
label="Release the Application" label="Release the Application"
labelPosition="right" labelPosition="right"
onToggle={this._handleToggle.bind(this)} onToggle={this.handleToggle.bind(this)}
defaultToggled={this.state.showForm} defaultToggled={this.state.showForm}
/> />
{/*If toggle is true, the release form will be shown.*/} {/*If toggle is true, the release form will be shown.*/}
{!this.state.showForm ? <div/> : <div> {!this.state.showForm ? <div/> :
<SelectField <div>
floatingLabelText="Select Release Channel*" <SelectField
value={this.state.releaseChannel} floatingLabelText="Select Release Channel*"
floatingLabelFixed={true} value={this.state.releaseChannel}
> floatingLabelFixed={true}
<MenuItem value={1} primaryText="Alpha"/> >
<MenuItem value={2} primaryText="Beta"/> <MenuItem value={1} primaryText="Alpha"/>
<MenuItem value={3} primaryText="GA"/> <MenuItem value={2} primaryText="Beta"/>
</SelectField> <br/> <MenuItem value={3} primaryText="GA"/>
<TextField </SelectField>
hintText="1.0.0" <br/>
floatingLabelText="Version*" <TextField
errorText={this.state.errors["title"]} hintText="1.0.0"
floatingLabelFixed={true} floatingLabelText="Version*"
/><br/> errorText={this.state.errors["title"]}
</div>} floatingLabelFixed={true}
/><br/>
</div>}
<div className="applicationCreateBackAndFinish"> <div className="applicationCreateBackAndFinish">
<FlatButton label="< Back" disabled={false} onClick={this._handlePrev.bind(this)} <FlatButton
className="applicationCreateFinish"/> label="< Back"
disabled={false}
onClick={this.handlePrev.bind(this)}
className="applicationCreateFinish"/>
<RaisedButton <RaisedButton
label="Finish" label="Finish"
primary={true} primary={true}
onClick={this._handleFinish.bind(this)} onClick={this.handleFinish.bind(this)}
/> />
</div> </div>
</div> </div>
</div> </div>

@ -97,67 +97,74 @@ class BaseLayout extends Component {
return ( return (
<div> <div>
<AppBar title="App Publisher" <AppBar
iconElementRight={ title="App Publisher"
<div> iconElementRight={
<Badge <div>
badgeContent={this.state.notifications} <Badge
secondary={true} badgeContent={this.state.notifications}
badgeStyle={{top: 12, right: 12}} secondary={true}
> badgeStyle={{top: 12, right: 12}}
<IconButton tooltip="Notifications"> >
<NotificationsIcon/> <IconButton tooltip="Notifications">
</IconButton> <NotificationsIcon/>
</Badge>
<IconButton onClick={() => {
console.log("Clicked")
}}>
<ActionAccountCircle/>
</IconButton> </IconButton>
</div> </Badge>
} <IconButton onClick={() => {
console.log("Clicked")
}}>
<ActionAccountCircle/>
</IconButton>
</div>
}
/> />
<div> <div>
<Drawer containerStyle={{height: 'calc(100% - 64px)', width: '15%', top: '10%'}} open={true}> <Drawer containerStyle={{height: 'calc(100% - 64px)', width: '15%', top: '10%'}} open={true}>
<List> <List>
<ListItem primaryText="Applications" <ListItem
leftIcon={<Apps/>} primaryText="Applications"
initiallyOpen={false} leftIcon={<Apps/>}
primaryTogglesNestedList={true} initiallyOpen={false}
onClick={this.handleApplicationClick.bind(this)} primaryTogglesNestedList={true}
nestedItems={[ onClick={this.handleApplicationClick.bind(this)}
<ListItem nestedItems={[
key={1} <ListItem
primaryText="Create" key={1}
onClick={this.handleApplicationCreateClick.bind(this)} primaryText="Create"
leftIcon={<Add/>} onClick={this.handleApplicationCreateClick.bind(this)}
/>]} leftIcon={<Add/>}
/>
]}
/> />
<ListItem primaryText="Platforms" <ListItem
leftIcon={<DevicesOther/>} primaryText="Platforms"
initiallyOpen={false} leftIcon={<DevicesOther/>}
primaryTogglesNestedList={true} initiallyOpen={false}
onClick={this.handlePlatformClick.bind(this)} primaryTogglesNestedList={true}
nestedItems={[ onClick={this.handlePlatformClick.bind(this)}
<ListItem nestedItems={[
key={1} <ListItem
primaryText="Create" key={1}
onClick={this.handlePlatformCreateClick.bind(this)} primaryText="Create"
leftIcon={<Add/>} onClick={this.handlePlatformCreateClick.bind(this)}
/>]} leftIcon={<Add/>}
/>
]}
/>
<ListItem
primaryText="Reviews"
onClick={this.handleReviewClick.bind(this)}
leftIcon={<Feedback/>}
/> />
<ListItem primaryText="Reviews"
onClick={this.handleReviewClick.bind(this)}
leftIcon={<Feedback/>}/>
</List> </List>
</Drawer> </Drawer>
</div> </div>
<div className="basicLayoutDiv"> <div className="basicLayoutDiv">
{this.props.children} {this.props.children}
</div> </div>
</div>); </div>
);
} }
} }
BaseLayout.propTypes = { BaseLayout.propTypes = {

@ -17,7 +17,6 @@
*/ */
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Axios from 'axios';
import Chip from 'material-ui/Chip'; import Chip from 'material-ui/Chip';
import Dropzone from 'react-dropzone'; import Dropzone from 'react-dropzone';
import React, {Component} from 'react'; import React, {Component} from 'react';
@ -34,6 +33,7 @@ import Close from 'material-ui/svg-icons/navigation/close';
import {Card, CardActions, CardTitle} from 'material-ui/Card'; import {Card, CardActions, CardTitle} from 'material-ui/Card';
import AddCircleOutline from 'material-ui/svg-icons/content/add-circle-outline'; import AddCircleOutline from 'material-ui/svg-icons/content/add-circle-outline';
import Theme from '../../theme'; import Theme from '../../theme';
import Endpoint from '../../api/endpoints';
/** /**
* Platform Create component. * Platform Create component.
@ -61,6 +61,7 @@ class PlatformCreate extends Component {
description: "", description: "",
property: "", property: "",
icon: [], icon: [],
identifier: "",
propertyTypes: [ propertyTypes: [
{key: 0, value: 'String'}, {key: 0, value: 'String'},
{key: 1, value: 'Number'}, {key: 1, value: 'Number'},
@ -74,7 +75,7 @@ class PlatformCreate 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() {
@ -85,7 +86,7 @@ class PlatformCreate extends Component {
* Handles toggle button actions. * Handles toggle button actions.
* One method is used for all the toggle buttons and, each toggle is identified by the id. * One method is used for all the toggle buttons and, each toggle is identified by the id.
* */ * */
_handleToggle(event) { handleToggle(event) {
switch (event.target.id) { switch (event.target.id) {
case "enabled" : { case "enabled" : {
let enabled = this.state.enabled; let enabled = this.state.enabled;
@ -103,28 +104,28 @@ class PlatformCreate extends Component {
/** /**
* Triggers the onChange action on property type selection. * Triggers the onChange action on property type selection.
* */ * */
_onPropertySelect = (event, index, value) => { onPropertySelect(event, index, value) {
console.log(this.state.propertyTypes[value]); console.log(this.state.propertyTypes[value]);
this.setState({selectedProperty: value}); this.setState({selectedProperty: value});
}; }
/** /**
* Handles Chip delete function. * Handles Chip delete function.
* Removes the tag from state.tags * Removes the tag from state.tags
* */ * */
_handleTagDelete = (key) => { handleTagDelete(key) {
this.chipData = this.state.tags; this.chipData = this.state.tags;
const chipToDelete = this.chipData.map((chip) => chip.key).indexOf(key); const chipToDelete = this.chipData.map((chip) => chip.key).indexOf(key);
this.chipData.splice(chipToDelete, 1); this.chipData.splice(chipToDelete, 1);
this.setState({tags: this.chipData}); this.setState({tags: this.chipData});
}; }
/** /**
* 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.
* Chip gets two parameters: Key and value. * Chip gets two parameters: Key and value.
* */ * */
_addTags(event) { addTags(event) {
let tags = this.state.tags; let tags = this.state.tags;
if (event.charCode === 13) { if (event.charCode === 13) {
event.preventDefault(); event.preventDefault();
@ -136,11 +137,11 @@ class PlatformCreate extends Component {
/** /**
* Creates Chip array from state.tags. * Creates Chip array from state.tags.
* */ * */
_renderChip(data) { renderChip(data) {
return ( return (
<Chip <Chip
key={data.key} key={data.key}
onRequestDelete={() => this._handleTagDelete(data.key)} onRequestDelete={() => this.handleTagDelete(data.key)}
style={this.styles.chip} style={this.styles.chip}
> >
{data.value} {data.value}
@ -151,7 +152,7 @@ class PlatformCreate extends Component {
/** /**
* Set the value for tag. * Set the value for tag.
* */ * */
_handleTagChange(event) { handleTagChange(event) {
let defaultValue = this.state.defValue; let defaultValue = this.state.defValue;
defaultValue = event.target.value; defaultValue = event.target.value;
this.setState({defValue: defaultValue}) this.setState({defValue: defaultValue})
@ -160,7 +161,7 @@ class PlatformCreate extends Component {
/** /**
* Remove the selected property from the property list. * Remove the selected property from the property list.
* */ * */
_removeProperty(property) { removeProperty(property) {
let properties = this.state.platformProperties; let properties = this.state.platformProperties;
properties.splice(properties.indexOf(property), 1); properties.splice(properties.indexOf(property), 1);
this.setState({platformProperties: properties}); this.setState({platformProperties: properties});
@ -169,28 +170,31 @@ class PlatformCreate extends Component {
/** /**
* Add a new platform property. * Add a new platform property.
* */ * */
_addProperty() { addProperty() {
let property = this.state.property; let property = this.state.property;
let selected = this.state.selectedProperty; let selected = this.state.selectedProperty;
this.setState({platformProperties: this.setState({
this.state.platformProperties.concat([ platformProperties:
{ this.state.platformProperties.concat([
key: property, {
value: this.state.propertyTypes[selected].value key: property,
}]), value: this.state.propertyTypes[selected].value
}]),
property: "", property: "",
selectedProperty: 0}); selectedProperty: 0
});
} }
/** /**
* Triggers in onChange event of text fields. * Triggers in onChange event of text fields.
* Text fields are identified by their ids and the value will be persisted in the component state. * Text fields are identified by their ids and the value will be persisted in the component state.
* */ * */
_onTextChange = (event, value) => { onTextChange(event, value) {
let property = this.state.property; let property = this.state.property;
let name = this.state.name; let name = this.state.name;
let description = this.state.description; let description = this.state.description;
let identifier = this.state.identifier;
switch (event.target.id) { switch (event.target.id) {
case "name": { case "name": {
@ -210,13 +214,26 @@ class PlatformCreate extends Component {
this.setState({property: property}); this.setState({property: property});
break; break;
} }
case "identifier": {
identifier = value;
this.setState({identifier: identifier});
}
} }
}; };
_onCreatePlatform() { onCreatePlatform() {
//Call the platform create api. //Call the platform create api.
let platform = {}; 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;
Endpoint.createPlatform(platform);
} }
@ -224,22 +241,24 @@ class PlatformCreate extends Component {
/** /**
* Remove the uploaded icon. * Remove the uploaded icon.
* */ * */
_removeIcon(event) { removeIcon(event) {
this.setState({icon: []}); this.setState({icon: []});
} }
/** /**
* Clears the user entered values in the form. * Clears the user entered values in the form.
* */ * */
_clearForm() { clearForm() {
this.setState({enabled: true, this.setState({
enabled: true,
allTenants: false, allTenants: false,
files: [], files: [],
platformProperties: [], platformProperties: [],
selectedProperty: 0, selectedProperty: 0,
name: "", name: "",
description: "", description: "",
property: "",}) property: "",
})
} }
render() { render() {
@ -253,24 +272,35 @@ class PlatformCreate extends Component {
tags, tags,
defValue, defValue,
description, description,
property} = this.state; identifier,
property
} = this.state;
return ( return (
<div className="middle createplatformmiddle"> <div className="middle createplatformmiddle">
<Card> <Card>
<CardTitle title="Create Platform"/> <CardTitle title="Create Platform"/>
<CardActions> <CardActions>
<div className="createplatformcardaction"> <div className="createplatformcardaction">
<form> <form>
<TextField
hintText="Unique Identifier for Platform."
id="identifier"
floatingLabelText="Identifier*"
floatingLabelFixed={true}
value={identifier}
onChange={this.onTextChange.bind(this)}
/>
<br/>
<TextField <TextField
hintText="Enter the Platform Name." hintText="Enter the Platform Name."
id="name" id="name"
floatingLabelText="Name*" floatingLabelText="Name*"
floatingLabelFixed={true} floatingLabelFixed={true}
value={name} value={name}
onChange={this._onTextChange.bind(this)} onChange={this.onTextChange.bind(this)}
/><br/> />
<br/>
<TextField <TextField
id="description" id="description"
hintText="Enter the Platform Description." hintText="Enter the Platform Description."
@ -279,33 +309,38 @@ class PlatformCreate extends Component {
multiLine={true} multiLine={true}
rows={2} rows={2}
value={description} value={description}
onChange={this._onTextChange.bind(this)} onChange={this.onTextChange.bind(this)}
/><br/><br/> />
<br/>
<br/>
<Toggle <Toggle
id="tenant" id="tenant"
label="Shared with all Tenants" label="Shared with all Tenants"
labelPosition="right" labelPosition="right"
onToggle={this._handleToggle.bind(this)} onToggle={this.handleToggle.bind(this)}
toggled={allTenants} toggled={allTenants}
/> <br/> />
<br/>
<Toggle <Toggle
id="enabled" id="enabled"
label="Enabled" label="Enabled"
labelPosition="right" labelPosition="right"
onToggle={this._handleToggle.bind(this)} onToggle={this.handleToggle.bind(this)}
toggled={enabled} toggled={enabled}
/> <br/> />
<br/>
<TextField <TextField
id="tags" id="tags"
hintText="Enter Platform tags.." hintText="Enter Platform tags.."
floatingLabelText="Tags*" floatingLabelText="Tags*"
floatingLabelFixed={true} floatingLabelFixed={true}
value={defValue} value={defValue}
onChange={this._handleTagChange.bind(this)} onChange={this.handleTagChange.bind(this)}
onKeyPress={this._addTags.bind(this)} onKeyPress={this.addTags.bind(this)}
/><br/> />
<br/>
<div style={this.styles.wrapper}> <div style={this.styles.wrapper}>
{tags.map(this._renderChip, this)} {tags.map(this.renderChip, this)}
</div> </div>
<br/> <br/>
<div> <div>
@ -313,7 +348,7 @@ class PlatformCreate extends Component {
<div id="property-container"> <div id="property-container">
{platformProperties.map((p) => { {platformProperties.map((p) => {
return <div key={p.key}>{p.key} : {p.value} return <div key={p.key}>{p.key} : {p.value}
<IconButton onClick={this._removeProperty.bind(this, p)}> <IconButton onClick={this.removeProperty.bind(this, p)}>
<Close className="createplatformpropertyclose"/> <Close className="createplatformpropertyclose"/>
</IconButton> </IconButton>
</div> </div>
@ -326,21 +361,21 @@ class PlatformCreate extends Component {
floatingLabelText="Platform Property*" floatingLabelText="Platform Property*"
floatingLabelFixed={true} floatingLabelFixed={true}
value={this.state.property} value={this.state.property}
onChange={this._onTextChange.bind(this)} onChange={this.onTextChange.bind(this)}
/> <em/> /> <em/>
<SelectField <SelectField
className="createplatformpropertyselect" className="createplatformpropertyselect"
floatingLabelText="Property Type" floatingLabelText="Property Type"
value={selectedProperty} value={selectedProperty}
floatingLabelFixed={true} floatingLabelFixed={true}
onChange={this._onPropertySelect.bind(this)}> onChange={this.onPropertySelect.bind(this)}>
{propertyTypes.map((type) => { {propertyTypes.map((type) => {
return <MenuItem key={type.key} return <MenuItem key={type.key}
value={type.key} value={type.key}
primaryText={type.value}/> primaryText={type.value}/>
})} })}
</SelectField> </SelectField>
<IconButton onClick={this._addProperty.bind(this)}> <IconButton onClick={this.addProperty.bind(this)}>
<AddCircleOutline/> <AddCircleOutline/>
</IconButton> </IconButton>
<br/> <br/>
@ -350,27 +385,33 @@ class PlatformCreate extends Component {
<p className="createplatformiconp">Platform Icon*:</p> <p className="createplatformiconp">Platform Icon*:</p>
<GridList className="createplatformicon" cols={1.1}> <GridList className="createplatformicon" cols={1.1}>
{this.state.icon.map((tile) => ( {this.state.icon.map((tile) => (
<GridTile key={Math.floor(Math.random() * 1000)} <GridTile
title={tile.name} key={Math.floor(Math.random() * 1000)}
actionIcon={ title={tile.name}
<IconButton onClick={this._removeIcon.bind(this)}> actionIcon={
<Clear /> <IconButton onClick={this.removeIcon.bind(this)}>
</IconButton>}> <Clear/>
</IconButton>}>
<img src={tile.preview}/> <img src={tile.preview}/>
</GridTile> </GridTile>
))} ))}
{this.state.icon.length === 0 ? {this.state.icon.length === 0 ?
<Dropzone className="createplatformdropzone" <Dropzone
accept="image/jpeg, image/png" className="createplatformdropzone"
onDrop={(icon, rejected) => {this.setState({icon, rejected})}}> accept="image/jpeg, image/png"
onDrop={(icon, rejected) => {
this.setState({icon, rejected})
}}
>
<p className="createplatformdropzonep">+</p> <p className="createplatformdropzonep">+</p>
</Dropzone> : <div />} </Dropzone> : <div/>}
</GridList> </GridList>
</div> </div>
<br/> <br/>
<RaisedButton primary={true} label="Create" <RaisedButton
onClick={this._onCreatePlatform.bind(this)}/> primary={true} label="Create"
<FlatButton label="Cancel" onClick={this._clearForm.bind(this)}/> onClick={this.onCreatePlatform.bind(this)}/>
<FlatButton label="Cancel" onClick={this.clearForm.bind(this)}/>
</form> </form>
</div> </div>
</CardActions> </CardActions>
@ -380,7 +421,6 @@ class PlatformCreate extends Component {
} }
} }
PlatformCreate.prototypes = { PlatformCreate.prototypes = {};
};
export default PlatformCreate; export default PlatformCreate;

@ -56,7 +56,7 @@ class PlatformListing extends Component {
* Handles the search action. * Handles the search action.
* When typing in the search bar, this method will be invoked. * When typing in the search bar, this method will be invoked.
* */ * */
_searchApplications(word) { searchApplications(word) {
let searchedData = []; let searchedData = [];
} }
@ -64,13 +64,13 @@ class PlatformListing extends Component {
* Handles sort data function and toggles the asc state. * Handles sort data function and toggles the asc state.
* asc: true : sort in ascending order. * asc: true : sort in ascending order.
* */ * */
_sortData() { sortData() {
let isAsc = this.state.asc; let isAsc = this.state.asc;
let datas = isAsc?this.data.sort(this._compare):this.data.reverse(); let datas = isAsc ? this.data.sort(this.compare) : this.data.reverse();
this.setState({data: datas, asc: !isAsc}); this.setState({data: datas, asc: !isAsc});
} }
_compare(a, b) { compare(a, b) {
if (a.applicationName < b.applicationName) if (a.applicationName < b.applicationName)
return -1; return -1;
if (a.applicationName > b.applicationName) if (a.applicationName > b.applicationName)
@ -78,24 +78,25 @@ class PlatformListing extends Component {
return 0; return 0;
} }
_onRowClick(id) { onRowClick(id) {
console.log(id) console.log(id)
} }
render() { render() {
return ( return (
<div className= 'middle listingplatformmiddle'> <div className='middle listingplatformmiddle'>
<Card className='listingplatformcard'> <Card className='listingplatformcard'>
<TextField hintText="Search" onChange={this._searchApplications.bind(this)} <TextField hintText="Search" onChange={this.searchApplications.bind(this)}
className='listingplatformsearch'/> className='listingplatformsearch'/>
<CardTitle title="Platforms" className='listingplatformTitle'/> <CardTitle title="Platforms" className='listingplatformTitle'/>
<CardActions> <CardActions>
</CardActions> </CardActions>
<DataTable headers={this.headers} <DataTable
data={this.data} headers={this.headers}
handleRowClick={this._onRowClick.bind(this)} data={this.data}
noDataMessage={{type: 'button', text: 'Create Platform'}}/> handleRowClick={this.onRowClick.bind(this)}
noDataMessage={{type: 'button', text: 'Create Platform'}}/>
</Card> </Card>
</div> </div>
); );

@ -83,7 +83,7 @@ class DataTable extends Component {
* Triggers when user click on table row. * Triggers when user click on table row.
* This method invokes the parent method handleRowClick, which is passed via props. * This method invokes the parent method handleRowClick, which is passed via props.
* */ * */
_handleRowClick(id) { handleRowClick(id) {
this.props.handleRowClick(id); this.props.handleRowClick(id);
} }
@ -100,22 +100,29 @@ class DataTable extends Component {
if (data) { if (data) {
return (<Table return (<Table
selectable={ false }> selectable={false}>
<TableHeader displaySelectAll={ false } <TableHeader displaySelectAll={false} adjustForCheckbox={false}>
adjustForCheckbox={ false }>
<TableRow> <TableRow>
{headers.map((header) => { {headers.map((header) => {
return (<DataTableHeader key={header.data_id} className="datatableRowColumn" return (
header={header}/>) <DataTableHeader
} key={header.data_id}
className="datatableRowColumn"
header={header}
/>
)}
)} )}
</TableRow> </TableRow>
</TableHeader> </TableHeader>
<TableBody> <TableBody>
{data.map((dataItem) =>{ {data.map((dataItem) => {
return (<DataTableRow key={dataItem.id} return (
dataItem={dataItem} <DataTableRow
handleClick={this._handleRowClick.bind(this)}/>) key={dataItem.id}
dataItem={dataItem}
handleClick={this.handleRowClick.bind(this)}
/>
)
})} })}
</TableBody> </TableBody>
</Table>) </Table>)

@ -48,7 +48,7 @@ class DataTableHeader extends Component {
* The onClick function of the table header. * The onClick function of the table header.
* Invokes the function passed in the header object. * Invokes the function passed in the header object.
* */ * */
_tableHeaderClick() { tableHeaderClick() {
this.props.header.sort(); this.props.header.sort();
} }
@ -60,14 +60,18 @@ class DataTableHeader extends Component {
* else create a span element with label as the table header. * else create a span element with label as the table header.
* */ * */
if (this.props.header.sortable) { if (this.props.header.sortable) {
headerCell = <FlatButton label={this.props.header.label} headerCell =
onClick={this._tableHeaderClick.bind(this)} className="sortableHeaderCell"/>; <FlatButton
label={this.props.header.label}
onClick={this.tableHeaderClick.bind(this)}
className="sortableHeaderCell"
/>;
} else { } else {
headerCell = <span className="notsortableHeaderCell">{this.props.header.label}</span>; headerCell = <span className="notsortableHeaderCell">{this.props.header.label}</span>;
} }
return ( return (
<TableHeaderColumn key={this.props.header.id} className="datatableHeaderColumn" > <TableHeaderColumn key={this.props.header.id} className="datatableHeaderColumn">
{headerCell} {headerCell}
</TableHeaderColumn> </TableHeaderColumn>
); );

@ -41,7 +41,7 @@ class DataTableRow 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() {
@ -51,24 +51,32 @@ class DataTableRow extends Component {
/** /**
* Triggers the click event on the data table row. * Triggers the click event on the data table row.
* */ * */
_handleClick() { handleClick() {
this.props.handleClick(this.state.dataItem.id); this.props.handleClick(this.state.dataItem.id);
} }
render() { render() {
const {dataItem} = this.state; const {dataItem} = this.state;
return ( return (
<TableRow key={this.props.key} onClick={this._handleClick.bind(this)} > <TableRow
{Object.keys(dataItem).map((key) => { key={this.props.key}
if (key !== 'id') { onClick={this.handleClick.bind(this)}
return <TableRowColumn className = "datatableRowColumn" >
key={key}>{dataItem[key]}</TableRowColumn> {Object.keys(dataItem).map((key) => {
} else { if (key !== 'id') {
return <TableRowColumn key={key}/> return (
} <TableRowColumn
className="datatableRowColumn"
key={key}
>
{dataItem[key]}
</TableRowColumn>)
} else {
return <TableRowColumn key={key}/>
}
} )} })}
</TableRow> </TableRow>
); );
} }
} }

@ -22,6 +22,7 @@ import React, {Component} from 'react';
import Checkbox from 'material-ui/Checkbox'; import Checkbox from 'material-ui/Checkbox';
import TextField from 'material-ui/TextField'; 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 RaisedButton from 'material-ui/RaisedButton'; import RaisedButton from 'material-ui/RaisedButton';
import {Card, CardActions, CardTitle} from 'material-ui/Card'; import {Card, CardActions, CardTitle} from 'material-ui/Card';
@ -65,15 +66,15 @@ class Login extends Component {
// } // }
} }
_handleLogin(event) { handleLogin(event) {
event.preventDefault(); event.preventDefault();
this._validateForm(); this.validateForm();
} }
/** /**
* Handles the username field change event. * Handles the username field change event.
* */ * */
_onUserNameChange(event, value) { onUserNameChange(event, value) {
this.setState( this.setState(
{ {
userName: value userName: value
@ -84,7 +85,7 @@ class Login extends Component {
/** /**
* Handles the password field change event. * Handles the password field change event.
* */ * */
_onPasswordChange(event, value) { onPasswordChange(event, value) {
this.setState( this.setState(
{ {
password: value password: value
@ -95,7 +96,7 @@ class Login extends Component {
/** /**
* Handles the remember me check. * Handles the remember me check.
* */ * */
_handleRememberMe() { handleRememberMe() {
this.setState( this.setState(
{ {
rememberMe: !this.state.rememberMe rememberMe: !this.state.rememberMe
@ -106,17 +107,32 @@ class Login extends Component {
/** /**
* Validate the login form. * Validate the login form.
* */ * */
_validateForm() { validateForm() {
let errors = {}; let errors = {};
let validationFailed = true;
if (!this.state.password) { if (!this.state.password) {
errors["passwordError"] = "Password is Required"; errors["passwordError"] = "Password is Required";
validationFailed = true;
} else {
validationFailed = false;
} }
if (!this.state.userName) { if (!this.state.userName) {
errors["userNameError"] = "User Name is Required"; errors["userNameError"] = "User Name is Required";
validationFailed = true;
} else {
validationFailed = false;
} }
this.setState({errors: errors}, console.log(errors)); if (validationFailed) {
this.setState({errors: errors}, console.log(errors));
} else {
let loginPromis = AuthHandler.login(this.state.userName, this.state.password);
loginPromis.then(response => {
console.log(AuthHandler.getUser());
this.setState({isLoggedIn: AuthHandler.getUser()});
})
}
} }
render() { render() {
@ -124,13 +140,12 @@ class Login extends Component {
if (!this.state.isLoggedIn) { if (!this.state.isLoggedIn) {
return ( return (
<div> <div>
{/*TODO: Style the components.*/} {/*TODO: Style the components.*/}
<Card> <Card>
<CardTitle title="WSO2 IoT App Publisher"/> <CardTitle title="WSO2 IoT App Publisher"/>
<CardActions> <CardActions>
<form onSubmit={this._handleLogin.bind(this)}> <form onSubmit={this.handleLogin.bind(this)}>
<TextField <TextField
hintText="Enter the User Name." hintText="Enter the User Name."
id="username" id="username"
@ -138,8 +153,9 @@ class Login extends Component {
floatingLabelText="User Name*" floatingLabelText="User Name*"
floatingLabelFixed={true} floatingLabelFixed={true}
value={this.state.userName} value={this.state.userName}
onChange={this._onUserNameChange.bind(this)} onChange={this.onUserNameChange.bind(this)}
/><br/> />
<br/>
<TextField <TextField
hintText="Enter the Password." hintText="Enter the Password."
id="password" id="password"
@ -148,11 +164,14 @@ class Login extends Component {
floatingLabelText="Password*" floatingLabelText="Password*"
floatingLabelFixed={true} floatingLabelFixed={true}
value={this.state.password} value={this.state.password}
onChange={this._onPasswordChange.bind(this)} onChange={this.onPasswordChange.bind(this)}
/><br/> />
<Checkbox label="Remember me." <br/>
onCheck={this._handleRememberMe.bind(this)} <Checkbox
checked={this.state.rememberMe}/> label="Remember me."
onCheck={this.handleRememberMe.bind(this)}
checked={this.state.rememberMe}
/>
<br/> <br/>
<RaisedButton type="submit" label="Login"/> <RaisedButton type="submit" label="Login"/>
</form> </form>

@ -21,7 +21,6 @@ import NotFound from './Error/NotFound';
import BaseLayout from './Base/BaseLayout'; import BaseLayout from './Base/BaseLayout';
import PlatformCreate from './Platform/PlatformCreate'; import PlatformCreate from './Platform/PlatformCreate';
import PlatformListing from './Platform/PlatformListing'; import PlatformListing from './Platform/PlatformListing';
import PublisherOverview from './Overview/PublisherOverview';
import ApplicationCreate from './Application/ApplicationCreate'; import ApplicationCreate from './Application/ApplicationCreate';
import ApplicationListing from './Application/ApplicationListing'; import ApplicationListing from './Application/ApplicationListing';
@ -29,5 +28,4 @@ import ApplicationListing from './Application/ApplicationListing';
* 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, PublisherOverview, export {Login, BaseLayout, ApplicationCreate, ApplicationListing, PlatformListing, NotFound, PlatformCreate};
PlatformCreate};

Loading…
Cancel
Save