Merge pull request #1001 from menakaj/application-mgt

WSO2 Font integration and Custom components.
merge-requests/7/head
sinthuja 7 years ago committed by GitHub
commit c0609887b6

@ -21,14 +21,14 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000"> <meta name="theme-color" content="#000000">
<link rel="stylesheet" type="text/css" href="./css/font-wso2.css"> <link rel="stylesheet" type="text/css" href="/css/font-wso2.css">
<link rel="stylesheet" type="text/css" href="./themes/index.css"> <link rel="stylesheet" type="text/css" href="/themes/default/default-theme.css">
<!-- <!--
manifest.json provides metadata used when your web app is added to the manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/ homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
--> -->
<link rel="manifest" href="manifest.json"> <link rel="manifest" href="/manifest.json">
<link rel="shortcut icon" href="images/favicon.png"> <link rel="shortcut icon" href="/images/favicon.png">
<!-- <!--
Notice the use of %PUBLIC_URL% in the tags above. Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build. It will be replaced with the URL of the `public` folder during the build.
@ -45,7 +45,7 @@
You need to enable JavaScript to run this app. You need to enable JavaScript to run this app.
</noscript> </noscript>
<div id="root"></div> <div id="root"></div>
<script src='./dist/index.js'></script> <script src='/dist/index.js'></script>
<!-- <!--
This HTML file is a template. This HTML file is a template.
If you open it directly in the browser, you will see an empty page. If you open it directly in the browser, you will see an empty page.

@ -1,25 +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.
*/
.creatediv {
margin: 0 16px;
}
.nextButton {
margin-top: 12px;
}

@ -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.
*/
.applicationCreateChip {
margin: 4px;
}
.createStep2Content {
margin: 0 16px;
}
.applicationCreateWrapper {
display: flex;
flex-wrap: wrap;
}
.platformSpecificPropertyDiv {
border: solid #BDBDBD 1px;
}
.platformSpecificPropertyP {
color: #BDBDBD;
}
.applicationCreateBannerError {
color: #f44336;
}
.applicationCreateBannerTitle {
color: #BDBDBD;
}
.applicationCreateGrid {
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
}
.applicationCreateBannerDropZone {
width: 300px;
height: 150px;
border: dashed #BDBDBD 1px
}
.applicationCreateBannerp {
margin: 70px 40px 40px 150px;
}
.applicationCreateScreenshotError {
color: #f44336;
}
.applicationCreateScreenshotTitle {
color: #BDBDBD;
}
.applicationCreateScreenshotGrid {
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
}
.applicationCreateScreenshotDropZone {
width: 150px;
height: 150px;
border: dashed #BDBDBD 1px;
}
.applicationCreateScreenshotp {
margin: 70px 40px 70px 70px;
}
.applcationCreateIconError {
color: #f44336;
}
.applicationCreateIconTitle {
color: #BDBDBD;
}
.applicationCreateIconGrid {
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
}
.applicationCreateIconDropZone {
width: 150px;
height: 150px;
border: dashed #BDBDBD 1px;
}
.applicationCreateIconp {
margin: 70px 40px 70px 70px;
}
.applicationCreateBackAndNext {
margin-top: 12px;
}
.applicationCreateBack {
margin-right: 12px;
}

@ -1,29 +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.
*/
.applicationCreateStepMiddle {
margin: 0 16px;
}
.applicationCreateBackAndFinish {
margin-top: 12px;
}
.applicationCreateFinish {
margin-right: 12px;
}

@ -1,36 +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.
*/
.createapplicationmiddle {
width: 95%;
height: 100%;
margin-top: 1%;
}
.creataapplicationcard {
max-height: 700px;
overflow: auto;
}
.createapplicationcardaction {
width: 100%;
margin: auto;
}
.createapplicationcontent {
margin: 0 16px;
}

@ -1,38 +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.
*/
.applicationListingMiddle {
width: 95%;
height: 100%;
margin-top: 1%;
}
.applicationListingCard {
display: flex;
flex-wrap: wrap;
}
.applicationListingSearch {
float:right;
padding-right: 2px;
}
.applicationListTitle {
display: flex;
flex-wrap: wrap;
}

@ -1,25 +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.
*/
.basicLayoutDiv {
height: calc(100% - 64px);
margin-left: 16%;
width: calc(100% - 15%);
top: 64px;
left: -100px;
}

@ -1,43 +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.
*/
.tableRow {
display: flex;
}
.datatableRowColumn {
align-items: center;
}
.sortableHeaderCell {
color: #bdbdbd;
}
.notsortableHeaderCell {
position: relative;
padding-left: 16px;
padding-right: 16px;
text-transform: uppercase;
font-weight: normal;
color: #bdbdbd;
font-size: 14px;
}
.datatableHeaderColumn {
padding-left: 0;
}

@ -0,0 +1,483 @@
/*
* 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.
*/
/* Body Styling */
body {
width: 100%;
font-family: Roboto sans-serif;
}
/* Login page styles*/
#userName {
border-radius: 0;
}
#password {
border-radius: 0;
}
#login-btn {
border-radius: 0;
background-color: navy;
color: white;
cursor: pointer;
}
#login-container {
width: 50%;
margin: 0 auto
}
#login-card {
border-radius: 0;
background-color: #BaBaBa;
}
/* Base layout container */
#container {
background-color: #ffffff;
padding: 0;
}
/* Base layout header content*/
#header-content {
height: 125px;
width: 100%;
margin: 0 10px 0 0;
background-color: #3b33bd;
position: fixed; /* Set the navbar to fixed position */
top: 0; /* Position the navbar at the top of the page */
z-index: 2;
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
/* Contains the header styles.*/
#header {
margin: 16px 16px 20px 16px;
height: 100%;
position: relative;
}
#header-text {
color: #ffffff;
font-size: 25px;
top: 10px;
margin-left: 10px;
}
/* The buttons in the header (User and Notification)*/
#header-btn-container {
float: right;
}
.btn-header {
margin-top: 15px;
margin-right: 20px;
color: white;
}
/* Search box styles */
.search-icon {
position: absolute;
top: 5px;
left: 5px;
}
#search-box {
display: flex;
color: #a8a8a8;
position: relative;
float: right;
top: 75px;
left: 80px;
margin-right: 16px;
}
#search {
position: relative;
color: white;
background-color: transparent;
left: 15px;
top: 0px;
height: 25px;
outline: none;
border: none;
border-radius: 0%;
}
/* Application Add button */
#add-btn-container {
position: absolute;
left: 12%;
top: 100px;
}
/* Holds the app publisher pages. */
#application-content {
height: auto;
width: 80%;
margin: 150px auto;
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
padding: 10px 10px 10px 10px;
}
.stepper-header {
width: 100%;
border-bottom: solid 1px cornflowerblue;
padding-bottom: 5px;
margin-bottom: 10px;
}
.platform-link-placeholder {
color: #888888;
float: right;
margin-right: 20px;
padding-bottom: 10px;
}
#application-list {
margin-top: 20px;
transition: margin-right .5s;
}
#app-image-screenshot {
width: 300px;
height: 300px;
}
#app-image-icon {
width: 300px;
height: 300px;
}
#app-image-banner {
width: 400px;
height: 300px;
}
.application-create-banner-dropzone {
width: 300px;
height: 150px;
border-radius: 5%;
position: relative;
background-color: rgba(157, 159, 157, 0.53);
border: dashed #888888 2px;
}
.application-create-banner-dropzone i {
position: absolute;
top: 65px;
left: 145px;
}
.application-create-screenshot-dropzone {
width: 150px;
height: 150px;
margin: 0 5px 0 5px;
border-radius: 10%;
position: relative;
background-color: rgba(157, 159, 157, 0.53);
border: dashed #888888 2px;
}
.application-create-screenshot-dropzone i {
position: absolute;
top: 65px;
left: 65px;
}
.application-create-icon-dropzone {
width: 150px;
height: 150px;
border-radius: 10%;
position: relative;
background-color: rgba(157, 159, 157, 0.53);
border: dashed #888888 2px;
}
.application-create-icon-dropzone i {
position: absolute;
top: 65px;
left: 65px;
}
#screenshot-container {
display: flex;
overflow-x: auto;
height: 200px;
}
#app-icon-container {
height: 300px;
overflow-x: auto;
}
#modal-body-content {
max-height: 700px;
overflow-y: auto;
}
#img-btn-screenshot {
margin: 0 5px 0 5px;
}
#app-create-modal {
max-width: 700px;
overflow-x: auto;
}
#store {
border: none;
border-bottom: solid #BDBDBD 1px;
border-radius: 0px;
width: 200px;
}
#version {
border: none;
border-bottom: solid #BDBDBD 1px;
border-radius: 0px;
width: 200px;
}
#app-release-switch-content {
display: flex;
}
#app-release-switch-label {
position: absolute;
float: left;
}
#app-release-switch-switch {
position: absolute;
right: 10px;
}
.image-sub-title {
font-style: italic;
font-size: 12px;
color: #818181;
}
/* Application View */
#application-view-content {
width: 100%;
}
#application-view-row {
margin: 10px 10px 20px 20px;
}
#app-icon {
height: 100px;
width: 100px;
border: solid 1px black;
border-radius: 50%;
}
.app-updated-date {
color: #888888;
font-style: italic;
}
.app-install-count {
font-style: italic;
}
.app-details-tbl {
outline: none;
border-color: #2196F3;
}
.app-details-tbl tr {
margin: 20px 0 0 0;
}
.app-details-tbl td {
margin-left: 10px;
max-width: 400px;
}
/* Application Edit Base Layout */
#application-edit-header {
height: 50px;
width: 100%;
margin: 0;
font-size: 20px;
border-bottom: solid 1px #d8d8d8;
}
.application-header-text {
margin: 10px 0px 0px 10px;
}
#save-btn-content {
float: right;
}
#app-save-btn {
border-radius: 0%;
}
.save-btn {
margin: 5px 5px 5px 0px;
height: 70%;
width: 50%;
float: right;
}
.save-btn:hover {
cursor: pointer;
}
/*Tab styling*/
div.tab {
float: left;
border-right: 1px solid #d8d8d8;
height: 100%;
}
/* Style the tab buttons */
div.tab button {
display: block;
background-color: inherit;
color: black;
padding: 15px 16px;
width: 100%;
border: none;
outline: none;
text-align: left;
cursor: pointer;
transition: 0.3s;
}
/* Change background color of buttons on hover */
div.tab button:hover {
background-color: #ddd6d7;
cursor: pointer;
}
/* Create an active/current "tab button" class */
div.tab button.active {
background-color: #1b3bcc;
color: white;
}
#application-edit-main-container {
display: flex;
}
#application-edit-outer-content {
height: auto;
width: 100%;
}
#application-edit-content {
margin: 5px 10px 5px 10px;
width: 90%;
}
#app-edit-content {
height: 100%;
position: relative;
}
.back-to-app {
position: absolute;
height: 40px;
width: 40px;
border-radius: 50%;
}
.back-to-app i {
padding: 10px 10px 10px 10px;
}
.back-to-app:hover {
cursor: pointer;
background-color: #dedede;
transition: .5s;
}
/* Create Release and Release management */
.release-header {
margin-top: 20px;
margin-bottom: 20px;
}
.release-create {
height: 150px;
margin-bottom: 20px;
}
.release-detail-content {
width: 100%;
margin-top: 20%;
height: 300px;
}
.form-btn {
float: right;
margin-bottom: 10px;
}
.release-content {
height: 180px;
width: 95%;
border: dashed 1px #626262;
border-radius: 2%;
position: relative;
background-color: #e8e8e8;
}
.release-content:after {
content: "";
letter-spacing: 4px;
}
.release {
margin: 30px 10px 20px 30px;
}
.no-release-content {
position: absolute;
margin-top: 10px;
left: 40%;
}
.button-add:hover {
cursor: pointer;
}
.release-inner {
margin-top: 5%;
}
/* Application Edit General Info */
.app-edit-general-info {
margin-top: 20px;
max-width: 100%;
}
.save-info {
float: right;
margin-bottom: 10px;
}

@ -1,73 +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.
*/
.createplatformmiddle {
width: 95%;
height: 100%;
margin-top: 1%
}
.createplatformcardaction {
width: 100%;
margin: auto;
padding-left: 10px;
}
.createplatformproperties {
color: #BaBaBa;
}
.createplatformpropertyclose {
height: 10px;
width: 10px;
}
.createplatformproperty {
display: flex;
}
.createplatformpropertyselect {
flex: 1 1 23% 1;
margin: 0 1%
}
.createplatformicon {
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
}
.createplatformiconp {
color: #BDBDBD;
}
.createplatformdropzone {
width: 150px;
height: 150px;
border: dashed #BDBDBD 1px;
}
.createplatformdropzonep {
margin: 70px 40px 70px 70px
}
.createPlatformTagWrapper {
display: flex;
flex-wrap: wrap;
}

@ -1,39 +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.
*/
.listingplatformmiddle {
width: 95%;
height: 100%;
margin-top: 1%;
}
.listingplatformcard {
display: flex;
flex-wrap: wrap;
}
.listingplatformsearch {
float:right;
padding-right: 2px;
}
.listingplatformTitle {
display: flex;
flex-wrap: wrap;
}

@ -16,23 +16,19 @@
* under the License. * under the License.
*/ */
import './App.css';
import Theme from './theme';
import React, {Component} from 'react'; import React, {Component} from 'react';
import AuthHandler from './api/authHandler'; 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 getMuiTheme from 'material-ui/styles/getMuiTheme';
import { import {
ApplicationCreate, ApplicationCreate,
ApplicationEdit,
ApplicationListing, ApplicationListing,
BaseLayout, BaseLayout,
Login, Login,
NotFound, NotFound,
PlatformCreate, PlatformCreate,
PlatformListing, PlatformListing
ApplicationEdit
} from './components'; } from './components';
@ -65,19 +61,13 @@ class Base extends Component {
if (!AuthHandler.isTokenExpired()) { if (!AuthHandler.isTokenExpired()) {
this.setState({user: user}); this.setState({user: user});
} else { } else {
console.log("expired!");
this.setState({user: null}); this.setState({user: null});
} }
} }
} }
componentDidMount() {
}
render() { render() {
if (this.state.user !== null) { if (this.state.user !== null) {
console.log("Have User.");
return ( return (
<div> <div>
<BaseLayout user={this.state.user}> <BaseLayout user={this.state.user}>
@ -99,7 +89,6 @@ class Base extends Component {
</div> </div>
) )
} else { } else {
console.log("No user");
return (<Redirect to={"/login"}/>) return (<Redirect to={"/login"}/>)
} }
@ -120,53 +109,11 @@ class Publisher extends Component {
selectedType: null, selectedType: null,
selectedTheme: null selectedTheme: null
}; };
this.setTheme = this.setTheme.bind(this);
}
componentDidMount() {
/**
*Loading the theme files based on the the user-preference.
*/
let themeConfig = Theme.loadThemeConfigs();
themeConfig.then(this.setTheme).catch(function (error) {
console.log(error);
});
}
/**
* To set the theme based on the configuration file.
* @param response Configuration file data.
*/
setTheme(response) {
this.setState({
selectedType: response.data.theme.type,
selectedTheme: response.data.theme.value
});
Theme.currentThemeType = this.state.selectedType;
Theme.currentTheme = this.state.selectedTheme;
Theme.selectedTheme =
(Theme.currentThemeType === Theme.defaultThemeType) ? Theme.defaultThemeType : Theme.currentTheme;
if (this.state.selectedType === "default") {
let defaultTheme = require("material-ui/styles/baseThemes/" + this.state.selectedTheme);
this.setState({
muiTheme: getMuiTheme(defaultTheme.default)
});
} else {
let customTheme = require("./themes/" + this.state.selectedTheme);
this.setState({
muiTheme: getMuiTheme(customTheme.default)
});
}
} }
render() { render() {
return ( return (
<div className="App"> <div className="App">
<MuiThemeProvider>
<Router basename="publisher" history={history}> <Router basename="publisher" history={history}>
<Switch> <Switch>
<Route path="/login" component={Login}/> <Route path="/login" component={Login}/>
@ -174,7 +121,6 @@ class Publisher extends Component {
<Route component={Base}/> <Route component={Base}/>
</Switch> </Switch>
</Router> </Router>
</MuiThemeProvider>
</div> </div>
); );
} }

@ -20,12 +20,9 @@ import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {withRouter} from 'react-router-dom'; import {withRouter} from 'react-router-dom';
import AuthHandler from "../../api/authHandler"; import AuthHandler from "../../api/authHandler";
import NotificationsIcon from 'material-ui/svg-icons/social/notifications';
import ActionAccountCircle from 'material-ui/svg-icons/action/account-circle';
import ApplicationCreate from '../Application/Create/ApplicationCreate'; import ApplicationCreate from '../Application/Create/ApplicationCreate';
import {Button, Input, InputGroup, Popover, PopoverContent, PopoverTitle,} from 'reactstrap'; import {Col, Container, Input, Row,} from 'reactstrap';
import NotificationItem from '../UIComponents/Notifications/NotificationItem'; import FloatingButton from "../UIComponents/FloatingButton/FloatingButton";
/** /**
* Base Layout: * Base Layout:
@ -43,6 +40,7 @@ class BaseLayout extends Component {
openModal: false openModal: false
}; };
this.logout = this.logout.bind(this); this.logout = this.logout.bind(this);
this.closeModal = this.closeModal.bind(this);
} }
handleApplicationClick() { handleApplicationClick() {
@ -67,46 +65,49 @@ class BaseLayout extends Component {
AuthHandler.logout(); AuthHandler.logout();
} }
closeModal() {
this.setState({openModal: false});
}
render() { render() {
return ( return (
<div id="container"> <Container noGutters fluid id="container">
<div id="header-content"> <div id="header-content">
<div id="header"> <div id="header">
<span id="header-text"> <span id="header-text">
WSO2 IoT App Publisher WSO2 IoT App Publisher
</span> </span>
<div id="header-btn"> <div id="header-btn-container">
<Button className="btn-notification" id="btn"><NotificationsIcon/></Button> <i className="fw fw-notification btn-header"></i>
<Button className="btn-account" id="btn"><ActionAccountCircle/></Button> <i className="fw fw-user btn-header"></i>
</div>
</div> </div>
<div id="search-box"> <div id="search-box">
<InputGroup> <i className="fw fw-search search-icon">
</i>
<Input <Input
id="search" id="search"
name="search" name="search"
placeholder={'Search for Applications'} placeholder={'Search for Applications'}
onChange={(event) => console.log(event.target.value)} onChange={(event) => console.log(event.target.value)} //TODO: Remove this
/> />
</InputGroup> </div>
</div> </div>
<div id="add-btn-container"> <div id="add-btn-container">
<Button <FloatingButton
id="add-btn" className="add-btn small"
onClick={this.handleApplicationCreateClick.bind(this)} onClick={this.handleApplicationCreateClick.bind(this)}
> />
<h3>
<strong>+</strong>
</h3>
</Button>
</div> </div>
</div> </div>
<div id="application-content" style={this.state.style}> <div id="application-content" style={this.state.style}>
<Row>
<Col>
{this.props.children} {this.props.children}
</Col>
</Row>
</div> </div>
<ApplicationCreate open={this.state.openModal}/> <ApplicationCreate open={this.state.openModal} close={this.closeModal}/>
</div> </Container>
); );
} }
} }

@ -16,16 +16,11 @@
* under the License. * under the License.
*/ */
import Theme from '../../theme';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {withRouter} from 'react-router-dom'; import {withRouter} from 'react-router-dom';
import AuthHandler from "../../api/authHandler"; import {Button, Col, Row, Table} from 'reactstrap';
import ApplicationMgtApi from '../../api/applicationMgtApi';
import {Button, Row, Table} from 'reactstrap';
import Drawer from '../UIComponents/Drawer/Drawer'; import Drawer from '../UIComponents/Drawer/Drawer';
import ApplicationView from './View/ApplicationView'; import ApplicationView from './View/ApplicationView';
import NotificationView from "../UIComponents/Notifications/NotificationView";
import AppImage from "../UIComponents/AppImage/AppImage";
/** /**
* The App Create Component. * The App Create Component.
@ -52,10 +47,13 @@ class ApplicationListing extends Component {
application: {}, application: {},
drawer: {}, drawer: {},
appListStyle: {}, appListStyle: {},
//TODO: Remove this declaration.
image: [{id: "1", src: "https://www.greenfoot.org/images/logos/macos.png"}, image: [{id: "1", src: "https://www.greenfoot.org/images/logos/macos.png"},
{id: "2", src:"http://dl1.cbsistatic.com/i/r/2016/08/08/0e67e43a-5a45-41ab-b81d-acfba8708044/resize/736x552/0c0ee669677b5060a0fa1bfb0c7873b4/android-logo-promo-470.png"}] {
id: "2",
src: "http://dl1.cbsistatic.com/i/r/2016/08/08/0e67e43a-5a45-41ab-b81d-acfba8708044/resize/736x552/0c0ee669677b5060a0fa1bfb0c7873b4/android-logo-promo-470.png"
}]
}; };
this.scriptId = "application-listing";
} }
headers = [ headers = [
@ -127,19 +125,15 @@ class ApplicationListing extends Component {
componentWillMount() { componentWillMount() {
/** // let getApps = ApplicationMgtApi.getApplications();
*Loading the theme files based on the the user-preference. // getApps.then(response => {
*/ // let apps = this.setData(response.data.applications);
Theme.insertThemingScripts(this.scriptId); // console.log(apps); //TODO: Remove this.
let getApps = ApplicationMgtApi.getApplications(); // this.setState({searchedApplications: apps});
getApps.then(response => { // // console.log(this.setState({data: response.data}), console.log(this.state));
let apps = this.setData(response.data.applications); // }).catch(err => {
console.log(apps); //TODO: Remove this. // AuthHandler.unauthorizedErrorHandler(err);
this.setState({searchedApplications: apps}); // });
// console.log(this.setState({data: response.data}), console.log(this.state));
}).catch(err => {
AuthHandler.unauthorizedErrorHandler(err);
});
} }
/** /**
@ -200,7 +194,6 @@ class ApplicationListing extends Component {
} }
onRowClick() { onRowClick() {
console.log("sfsdfsdf");
let style = { let style = {
width: '500px', width: '500px',
marginLeft: '500px' marginLeft: '500px'
@ -227,8 +220,6 @@ class ApplicationListing extends Component {
return image.id !== imageId return image.id !== imageId
}); });
console.log(rem);
this.setState({image: rem}); this.setState({image: rem});
} }
@ -248,12 +239,24 @@ class ApplicationListing extends Component {
return ( return (
<div id="application-list" style={this.state.appListStyle}> <div id="application-list" style={this.state.appListStyle}>
<Row>
<Col xs="3 offset-9">
<div className="platform-link-placeholder">
<Button><i className="fw fw-settings"></i> Platforms</Button>
</div>
</Col>
</Row>
<Row>
<Col>
<Table striped hover> <Table striped hover>
<thead> <thead>
<tr> <tr>
<th></th> <th></th>
{/* TODO: Remove console.log and add sort method. */} {/* TODO: Remove console.log and add sort method. */}
<th onClick={() => {console.log("sort")}}>Application Name</th> <th onClick={() => {
console.log("sort")
}}>Application Name
</th>
<th>Category</th> <th>Category</th>
<th>Platform</th> <th>Platform</th>
<th>Status</th> <th>Status</th>
@ -278,14 +281,19 @@ class ApplicationListing extends Component {
<td>{application.category}</td> <td>{application.category}</td>
<td>{application.platform}</td> <td>{application.platform}</td>
<td>{application.status}</td> <td>{application.status}</td>
<td><Button onClick={this.handleButtonClick}>Edit</Button></td> <td>
<Button onClick={this.handleButtonClick}>
<i className="fw fw-edit"></i>
</Button>
</td>
</tr> </tr>
) )
} }
)} )}
</tbody> </tbody>
</Table> </Table>
</Col>
</Row>
<Drawer onClose={this.closeDrawer.bind(this)} style={this.state.drawer}> <Drawer onClose={this.closeDrawer.bind(this)} style={this.state.drawer}>
<ApplicationView/> <ApplicationView/>
</Drawer> </Drawer>

@ -21,7 +21,7 @@ import {withRouter} from 'react-router-dom';
import AuthHandler from "../../../api/authHandler"; import AuthHandler from "../../../api/authHandler";
import {Step1, Step2, Step3, Step4} from './CreateSteps/index'; import {Step1, Step2, Step3, Step4} from './CreateSteps/index';
import ApplicationMgtApi from '../../../api/applicationMgtApi'; import ApplicationMgtApi from '../../../api/applicationMgtApi';
import {Button, Modal, ModalBody, ModalFooter, ModalHeader} from 'reactstrap'; import {Button, Col, Modal, ModalBody, ModalFooter, ModalHeader, Row} from 'reactstrap';
/** /**
* The App Create Component. * The App Create Component.
@ -37,13 +37,13 @@ class ApplicationCreate extends Component {
this.scriptId = "application-create"; this.scriptId = "application-create";
this.setStepData = this.setStepData.bind(this); this.setStepData = this.setStepData.bind(this);
this.removeStepData = this.removeStepData.bind(this); this.removeStepData = this.removeStepData.bind(this);
this.handleSubmit = this.handleSubmit.bind(this); this.onSubmit = this.onSubmit.bind(this);
this.handleCancel = this.handleCancel.bind(this); this.handleCancel = this.handleCancel.bind(this);
this.handleYes = this.handleYes.bind(this); this.handleYes = this.handleYes.bind(this);
this.handleNo = this.handleNo.bind(this); this.handleNo = this.handleNo.bind(this);
this.handlePrev = this.handlePrev.bind(this); this.onPrevClick = this.onPrevClick.bind(this);
this.handleNext = this.handleNext.bind(this); this.onNextClick = this.onNextClick.bind(this);
this.close = this.close.bind(this); this.onClose = this.onClose.bind(this);
this.state = { this.state = {
finished: false, finished: false,
stepIndex: 0, stepIndex: 0,
@ -60,20 +60,16 @@ class ApplicationCreate extends Component {
this.setState({open: this.props.open}); this.setState({open: this.props.open});
} }
close() {
this.setState({open: false, stepIndex: 0})
}
handleBack() { onClose() {
let currentStep = this.state.stepIndex; this.setState({stepIndex: 0}, this.props.close());
let nextStep = currentStep === 0 ? currentStep : currentStep - 1 ;
this.setState({stepIndex: nextStep}, console.log(this.state.stepIndex));
} }
/** /**
* Handles next button click event. * Handles next button click event.
* */ * */
handleNext() { onNextClick() {
console.log("Handle Next"); //TODO: Remove this console.log("Handle Next"); //TODO: Remove this
const {stepIndex} = this.state; const {stepIndex} = this.state;
this.setState({ this.setState({
@ -85,10 +81,10 @@ class ApplicationCreate extends Component {
/** /**
* Handles form submit. * Handles form submit.
* */ * */
handleSubmit() { onSubmit() {
let stepData = this.state.stepData; let stepData = this.state.stepData;
let applicationCreationPromise = ApplicationMgtApi.createApplication(stepData); let applicationCreationPromise = ApplicationMgtApi.createApplication(stepData);
applicationCreationPromise.then( response => { applicationCreationPromise.then(response => {
this.handleYes(); this.handleYes();
} }
).catch( ).catch(
@ -110,7 +106,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() { onPrevClick() {
const {stepIndex} = this.state; const {stepIndex} = this.state;
if (stepIndex > 0) { if (stepIndex > 0) {
this.removeStepData(); this.removeStepData();
@ -128,7 +124,7 @@ class ApplicationCreate extends Component {
let tmpStepData = this.state.stepData; let tmpStepData = this.state.stepData;
tmpStepData.push({step: step, data: data}); tmpStepData.push({step: step, data: data});
this.setState({stepData: tmpStepData}, this.handleNext()) this.setState({stepData: tmpStepData}, this.onNextClick())
}; };
/** /**
@ -170,7 +166,7 @@ class ApplicationCreate extends Component {
case 0: case 0:
return ( return (
<Step1 <Step1
handleNext={this.handleNext} handleNext={this.onNextClick}
setData={this.setStepData} setData={this.setStepData}
removeData={this.removeStepData} removeData={this.removeStepData}
/> />
@ -178,8 +174,8 @@ class ApplicationCreate extends Component {
case 1: case 1:
return ( return (
<Step2 <Step2
handleNext={this.handleNext} handleNext={this.onNextClick}
handlePrev={this.handlePrev} handlePrev={this.onPrevClick}
setData={this.setStepData} setData={this.setStepData}
removeData={this.removeStepData} removeData={this.removeStepData}
/> />
@ -187,8 +183,8 @@ class ApplicationCreate extends Component {
case 2: case 2:
return ( return (
<Step3 <Step3
handleFinish={this.handleNext} handleFinish={this.onNextClick}
handlePrev={this.handlePrev} handlePrev={this.onPrevClick}
setData={this.setStepData} setData={this.setStepData}
removeData={this.removeStepData} removeData={this.removeStepData}
/> />
@ -196,7 +192,7 @@ class ApplicationCreate extends Component {
case 3: { case 3: {
return ( return (
<Step4 <Step4
handleNext={this.handleNext} handleNext={this.onNextClick}
setData={this.setStepData} setData={this.setStepData}
removeData={this.removeStepData} removeData={this.removeStepData}
/> />
@ -216,15 +212,26 @@ class ApplicationCreate extends Component {
backdrop={'static'}> backdrop={'static'}>
<ModalHeader toggle={this.toggle}>Create Application</ModalHeader> <ModalHeader toggle={this.toggle}>Create Application</ModalHeader>
<ModalBody id="modal-body-content"> <ModalBody id="modal-body-content">
{this.getStepContent(this.state.stepIndex)} <Row>
<Col>
<div className="stepper-header">
</div>
</Col>
</Row>
<Row>
<Col>
{this.getStepContent(stepIndex)}
</Col>
</Row>
</ModalBody> </ModalBody>
<ModalFooter> <ModalFooter>
{this.state.stepIndex === 0? <div/> : {stepIndex === 0 ? <div/> :
<Button color="primary" onClick={this.handlePrev}>Back</Button>} <Button color="primary" onClick={this.onPrevClick}>Back</Button>}
<Button color="secondary" onClick={this.close}>Cancel</Button> <Button color="secondary" onClick={this.onClose}>Cancel</Button>
{this.state.finished ? {finished ?
<Button color="primary" onClick={this.handleSubmit}>Finish</Button> : <Button color="primary" onClick={this.onSubmit}>Finish</Button> :
<Button color="primary" onClick={this.handleNext}>Continue</Button>} <Button color="primary" onClick={this.onNextClick}>Continue</Button>}
</ModalFooter> </ModalFooter>
</Modal> </Modal>
</div>); </div>);

@ -18,148 +18,194 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import AuthHandler from "../../../../api/authHandler"; import {Badge, FormGroup, Input, Label} from 'reactstrap';
import PlatformMgtApi from "../../../../api/platformMgtApi";
import {FormGroup, Input, Label} from 'reactstrap';
/** /**
* The first step of the application creation wizard. * The Second step of application create wizard.
* This contains following components: * This contains following components.
* * Application Title * * App Title
* * Store Type * * Short Description
* * Application Platform * * Application Description
* * Application Visibility
* * Application Tags : {Used Material UI Chip component}
* * Application Category.
* * Platform Specific properties.
* *
* Parent Component: Create * Parent Component: Create
* Props: * Props:
* 1. handleNext: {type: function, Invokes handleNext function of parent component} * * onNextClick : {type: function, Invokes onNextClick function in Parent.}
* 2. setData : {type: function, Sets current form data to the state of the parent component} * * onPrevClick : {type: function, Invokes onPrevClick function in Parent}
* 3. removeData: {type: function, Invokes the removeStepData function click of parent} * * setData : {type: function, Invokes setStepData function in Parent}
* * removeData : {type: Invokes removeStepData function in Parent}
* */ * */
class Step1 extends Component { class Step1 extends Component {
constructor() { constructor() {
super(); super();
this.setPlatforms = this.setPlatforms.bind(this);
this.setStepData = this.setStepData.bind(this);
this.cancel = this.cancel.bind(this);
this.platforms = [];
this.state = { this.state = {
finished: false, tags: [],
stepIndex: 0, icon: [],
store: 1,
platformSelectedIndex: 0,
platform: "",
platforms: [],
stepData: [],
title: "", title: "",
titleError: "" errors: {},
banner: [],
defValue: "",
category: 0,
visibility: 0,
description: "",
screenshots: [],
identifier: "",
shortDescription: ""
}; };
this.scriptId = "application-create-step1";
}
componentDidMount() {
//Get the list of available platforms and set to the state.
PlatformMgtApi.getPlatforms().then(response => {
console.log(response);
this.setPlatforms(response.data);
}).catch(err => {
AuthHandler.unauthorizedErrorHandler(err);
})
} }
/** /**
* Extract the platforms from the response data and populate the state. * Create a tag on Enter key press and set it to the state.
* @param platforms: The array returned as the response. * Clears the tags text field.
* Chip gets two parameters: Key and value.
* */ * */
setPlatforms(platforms) { addTags(event) {
let tmpPlatforms = []; let tags = this.state.tags;
for (let index in platforms) { if (event.charCode === 13) {
let platform = {}; event.preventDefault();
platform = platforms[index]; tags.push({key: Math.floor(Math.random() * 1000), value: event.target.value});
tmpPlatforms.push(platform); this.setState({tags, defValue: ""}, console.log(tags));
} }
this.setState({platforms: tmpPlatforms, platformSelectedIndex: 0, platform: tmpPlatforms[0].name})
} }
/** /**
* Persist the current form data to the state. * Set the value for tag.
* */ * */
setStepData() { handleTagChange(event) {
console.log("Platforms", this.state.platforms); let defaultValue = this.state.defValue;
let step = { defaultValue = event.target.value;
store: this.state.store, this.setState({defValue: defaultValue})
platform: this.state.platforms[this.state.platformSelectedIndex]
};
console.log(step);
this.props.setData("step1", {step: step});
}
cancel() {
} }
/** /**
* Triggers when changing the Platform selection. * Handles Chip delete function.
* Removes the tag from state.tags
* */ * */
onChangePlatform(event) { handleRequestDelete(event) {
console.log(event.target.value, this.state.platforms); this.chipData = this.state.tags;
let id = event.target.value; console.log(event.target);
let selectedPlatform = this.state.platforms.filter((platform) => { const chipToDelete = this.chipData.map((chip) => chip.value).indexOf(event.target.value);
return platform.identifier === id; this.chipData.splice(chipToDelete, 1);
}); this.setState({tags: this.chipData});
console.log(selectedPlatform); };
this.setState({platform: selectedPlatform}); /**
* Creates an object with the current step data and persist in the parent.
* */
setStepData() {
let stepData = {};
this.props.setData("step1", {step: stepData});
}; };
/** /**
* Triggers when changing the Store selection. * Set text field values to state.
* */ * */
onChangeStore(event) { onTextFieldChange(event, value) {
console.log(event.target.value); let field = event.target.id;
this.setState({store: event.target.value}); switch (field) {
case "name": {
this.setState({name: value});
break;
}
case "shortDescription": {
this.setState({shortDescription: value});
break;
}
case "description": {
this.setState({description: value});
break;
}
case "identifier": {
this.setState({identifier: value});
break;
}
}
}; };
render() { render() {
return ( return (
<div className="createStep2Content">
<div>
<div> <div>
<FormGroup> <FormGroup>
<Label for="store">Store Type</Label> <Label for="app-title">Title*</Label>
<Input
required
type="text"
name="appName"
id="app-title"
/>
</FormGroup>
<FormGroup>
<Label for="app-description">Description*</Label>
<Input
required
type="textarea"
name="appDescription"
id="app-description"
/>
</FormGroup>
<FormGroup>
<Label for="app-category">Category</Label>
<Input <Input
type="select" type="select"
name="store" name="category"
id="store" id="app-category"
className="input-custom"
onChange={this.onChangeStore.bind(this)}
> >
<option>Enterprise</option> <option>Business</option>
<option>Public</option>
</Input> </Input>
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<Label for="store">Platform</Label> <Label for="app-visibility">Visibility</Label>
<Input <Input
type="select" type="select"
name="store" name="visibility"
id="store" id="app-visibility"
onChange={this.onChangePlatform.bind(this)}
> >
{this.state.platforms.length > 0 ? this.state.platforms.map(platform => { <option>Devices</option>
<option>Roles</option>
<option>Groups</option>
</Input>
</FormGroup>
<FormGroup>
<Label for="app-tags">Tags*</Label>
<Input
required
type="text"
value={this.state.defValue}
name="app-tags"
id="app-tags"
onChange={this.handleTagChange.bind(this)}
onKeyPress={this.addTags.bind(this)}
/>
<div id="batch-content">
{this.state.tags.map(tag => {
return ( return (
<option value={platform.identifier}> <Badge
{platform.name} style={{margin: '0 2px 0 2px'}}
</option> value={tag.value}
onClick={this.handleRequestDelete.bind(this)}
>
{tag.value}
</Badge>
) )
}) : <option>No Platforms</option>} }
</Input> )}
</div>
</FormGroup> </FormGroup>
</div> </div>
</div>
</div>
); );
} }
} }
Step1.propTypes = { Step1.prototypes = {
handleNext: PropTypes.func, handleNext: PropTypes.func,
handlePrev: PropTypes.func,
setData: PropTypes.func, setData: PropTypes.func,
removeData: PropTypes.func removeData: PropTypes.func
}; };

@ -18,299 +18,135 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {Badge, FormGroup, Input, Label} from 'reactstrap'; import AuthHandler from "../../../../api/authHandler";
import PlatformMgtApi from "../../../../api/platformMgtApi";
import {FormGroup, Input, Label} from 'reactstrap';
/** /**
* The Second step of application create wizard. * The first step of the application creation wizard.
* This contains following components. * This contains following components:
* * App Title * * Application Title
* * Short Description * * Store Type
* * Application Description * * Application Platform
* * Application Visibility
* * Application Tags : {Used Material UI Chip component}
* * Application Category.
* * Platform Specific properties.
* *
* Parent Component: Create * Parent Component: Create
* Props: * Props:
* * handleNext : {type: function, Invokes handleNext function in Parent.} * 1. onNextClick: {type: function, Invokes onNextClick function of parent component}
* * handlePrev : {type: function, Invokes handlePrev function in Parent} * 2. setData : {type: function, Sets current form data to the state of the parent component}
* * setData : {type: function, Invokes setStepData function in Parent} * 3. removeData: {type: function, Invokes the removeStepData function click of parent}
* * removeData : {type: Invokes removeStepData function in Parent}
* */ * */
class Step2 extends Component { class Step2 extends Component {
constructor() { constructor() {
super(); super();
this.setPlatforms = this.setPlatforms.bind(this);
this.setStepData = this.setStepData.bind(this);
this.platforms = [];
this.state = { this.state = {
tags: [], finished: false,
icon: [], stepIndex: 0,
store: 1,
platformSelectedIndex: 0,
platform: "",
platforms: [],
stepData: [],
title: "", title: "",
errors: {}, titleError: ""
banner: [],
defValue: "",
category: 0,
visibility: 0,
description: "",
screenshots: [],
identifier: "",
shortDescription: ""
}; };
this.scriptId = "application-create-step2";
} }
/** componentDidMount() {
* Create a tag on Enter key press and set it to the state. //Get the list of available platforms and set to the state.
* Clears the tags text field. PlatformMgtApi.getPlatforms().then(response => {
* Chip gets two parameters: Key and value. console.log(response);
* */ this.setPlatforms(response.data);
addTags(event) { }).catch(err => {
let tags = this.state.tags; AuthHandler.unauthorizedErrorHandler(err);
if (event.charCode === 13) { })
event.preventDefault();
tags.push({key: Math.floor(Math.random() * 1000), value: event.target.value});
this.setState({tags, defValue: ""}, console.log(tags));
}
} }
/** /**
* Set the value for tag. * Extract the platforms from the response data and populate the state.
* @param platforms: The array returned as the response.
* */ * */
handleTagChange(event) { setPlatforms(platforms) {
let defaultValue = this.state.defValue; let tmpPlatforms = [];
defaultValue = event.target.value; for (let index in platforms) {
this.setState({defValue: defaultValue}) let platform = {};
platform = platforms[index];
tmpPlatforms.push(platform);
} }
this.setState({platforms: tmpPlatforms, platformSelectedIndex: 0, platform: tmpPlatforms[0].name})
/**
* Invokes the handleNext function in Create component.
* */
handleNext() {
let fields = [{name: "Title", value: this.state.title},
{name: "Short Description", value: this.state.shortDescription},
{name: "Description", value: this.state.description},
{name: "Banner", value: this.state.banner},
{name: "Screenshots", value: this.state.screenshots},
{name: "Identifier", value: this.state.identifier},
{name: "Icon", value: this.state.icon}];
this.validate(fields);
} }
/** /**
* Invokes the handlePrev function in Create component. * Persist the current form data to the state.
* */ * */
handlePrev() { setStepData() {
this.props.handlePrev(); let step = {
} store: this.state.store,
platform: this.state.platforms[this.state.platformSelectedIndex]
/**
* Handles Chip delete function.
* Removes the tag from state.tags
* */
handleRequestDelete(event) {
this.chipData = this.state.tags;
console.log(event.target);
const chipToDelete = this.chipData.map((chip) => chip.value).indexOf(event.target.value);
this.chipData.splice(chipToDelete, 1);
this.setState({tags: this.chipData});
}; };
this.props.setData("step2", {step: step});
/**
* Validate the form.
* */
validate(fields) {
let errors = {};
let errorsPresent = false;
fields.forEach(function (field) {
switch (field.name) {
case 'Title': {
if (field.value === "") {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Identifier': {
if (field.value === "") {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Short Description': {
if (field.value === "") {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Description': {
if (field.value === "") {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Banner': {
if (field.value.length === 0) {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Icon': {
if (field.value.length === 0) {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Screenshots': {
if (field.value.length < 3) {
errors[field.name] = "3 " + field.name + " are required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
}
});
if (!errorsPresent) {
this.setStepData();
} else {
this.setState({errors: errors}, console.log(errors));
}
} }
/** /**
* Creates an object with the current step data and persist in the parent. * Triggers when changing the Platform selection.
* */ * */
setStepData() { onChangePlatform(event) {
let stepData = {}; console.log(event.target.value, this.state.platforms);
let id = event.target.value;
this.props.setData("step2", {step: stepData}); let selectedPlatform = this.state.platforms.filter((platform) => {
return platform.identifier === id;
});
this.setState({platform: selectedPlatform});
}; };
/** /**
* Set text field values to state. * Triggers when changing the Store selection.
* */ * */
onTextFieldChange(event, value) { onChangeStore(event) {
let field = event.target.id; this.setState({store: event.target.value});
switch (field) {
case "name": {
this.setState({name: value});
break;
}
case "shortDescription": {
this.setState({shortDescription: value});
break;
}
case "description": {
this.setState({description: value});
break;
}
case "identifier": {
this.setState({identifier: value});
break;
}
}
}; };
render() { render() {
console.log(this.state.visibilityComponent);
return ( return (
<div className="createStep2Content">
<div>
<div> <div>
<FormGroup> <FormGroup>
<Label for="app-title">Title*</Label> <Label for="store">Store Type</Label>
<Input
required
type="text"
name="appName"
id="app-title"
/>
</FormGroup>
<FormGroup>
<Label for="app-description">Description*</Label>
<Input
required
type="textarea"
name="appDescription"
id="app-description"
/>
</FormGroup>
<FormGroup>
<Label for="app-category">Category</Label>
<Input <Input
type="select" type="select"
name="category" name="store"
id="app-category" className="input-custom"
onChange={this.onChangeStore.bind(this)}
> >
<option>Business</option> <option>Enterprise</option>
<option>Public</option>
</Input> </Input>
</FormGroup> </FormGroup>
<FormGroup> <FormGroup>
<Label for="app-visibility">Visibility</Label> <Label for="store">Platform</Label>
<Input <Input
type="select" type="select"
name="visibility" name="store"
id="app-visibility" onChange={this.onChangePlatform.bind(this)}
> >
<option>Devices</option> {this.state.platforms.length > 0 ? this.state.platforms.map(platform => {
<option>Roles</option>
<option>Groups</option>
</Input>
</FormGroup>
<FormGroup>
<Label for="app-tags">Tags*</Label>
<Input
required
type="text"
value={this.state.defValue}
name="app-tags"
id="app-tags"
onChange={this.handleTagChange.bind(this)}
onKeyPress={this.addTags.bind(this)}
/>
<div id="batch-content">
{this.state.tags.map(tag => {
return ( return (
<Badge <option value={platform.identifier}>
style={{margin: '0 2px 0 2px'}} {platform.name}
value={tag.value} </option>
onClick={this.handleRequestDelete.bind(this)}
>
{tag.value}
</Badge>
) )
} }) : <option>No Platforms</option>}
)} </Input>
</div>
</FormGroup> </FormGroup>
</div> </div>
</div>
</div>
); );
} }
} }
Step2.prototypes = { Step2.propTypes = {
handleNext: PropTypes.func, handleNext: PropTypes.func,
handlePrev: PropTypes.func,
setData: PropTypes.func, setData: PropTypes.func,
removeData: PropTypes.func removeData: PropTypes.func
}; };

@ -25,7 +25,6 @@ import SelectField from 'material-ui/SelectField';
import {FormGroup, Label} from 'reactstrap'; import {FormGroup, Label} from 'reactstrap';
import AppImage from "../../../UIComponents/AppImage/AppImage"; import AppImage from "../../../UIComponents/AppImage/AppImage";
/** /**
* The Third step of application create wizard. * The Third step of application create wizard.
* This contains following components. * This contains following components.
@ -35,8 +34,8 @@ import AppImage from "../../../UIComponents/AppImage/AppImage";
* *
* Parent Component: Create * Parent Component: Create
* Props: * Props:
* * handleNext : {type: function, Invokes handleNext function in Parent.} * * onNextClick : {type: function, Invokes onNextClick function in Parent.}
* * handlePrev : {type: function, Invokes handlePrev function in Parent} * * onPrevClick : {type: function, Invokes onPrevClick function in Parent}
* * setData : {type: function, Invokes setStepData function in Parent} * * setData : {type: function, Invokes setStepData function in Parent}
* * removeData : {type: Invokes removeStepData function in Parent} * * removeData : {type: Invokes removeStepData function in Parent}
* */ * */
@ -57,52 +56,6 @@ class Step3 extends Component {
identifier: "", identifier: "",
shortDescription: "" shortDescription: ""
}; };
this.scriptId = "application-create-step2";
}
/**
* 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: ""}, console.log(tags));
}
}
/**
* Set the value for tag.
* */
handleTagChange(event) {
let defaultValue = this.state.defValue;
defaultValue = event.target.value;
this.setState({defValue: defaultValue})
}
/**
* Invokes the handleNext function in Create component.
* */
handleNext() {
let fields = [{name: "Title", value: this.state.title},
{name: "Short Description", value: this.state.shortDescription},
{name: "Description", value: this.state.description},
{name: "Banner", value: this.state.banner},
{name: "Screenshots", value: this.state.screenshots},
{name: "Identifier", value: this.state.identifier},
{name: "Icon", value: this.state.icon}];
this.validate(fields);
}
/**
* Invokes the handlePrev function in Create component.
* */
handlePrev() {
this.props.handlePrev();
} }
/** /**
@ -111,170 +64,30 @@ class Step3 extends Component {
* */ * */
handleRequestDelete(event) { handleRequestDelete(event) {
this.chipData = this.state.tags; this.chipData = this.state.tags;
console.log(event.target); console.log(event.target); //TODO: Remove Console log.
const chipToDelete = this.chipData.map((chip) => chip.value).indexOf(event.target.value); const chipToDelete = this.chipData.map((chip) => chip.value).indexOf(event.target.value);
this.chipData.splice(chipToDelete, 1); this.chipData.splice(chipToDelete, 1);
this.setState({tags: this.chipData}); this.setState({tags: this.chipData});
}; };
/**
* Creates Chip array from state.tags.
* */
renderChip(data) {
return (
<Chip
key={data.key}
onRequestDelete={() => this.handleRequestDelete(data.key)}
className="applicationCreateChip">
{data.value}
</Chip>
);
}
onVisibilitySelect(event, index, value) {
console.log(value);
let comp = <SelectField> <MenuItem value={0} primaryText="Public"/>
<MenuItem value={1} primaryText="Roles"/>
<MenuItem value={2} primaryText="Devices"/> </SelectField>;
if (value === 1) {
this.setState({visibilityComponent: comp});
} else if (value === 2) {
} else {
}
};
/**
* Validate the form.
* */
validate(fields) {
let errors = {};
let errorsPresent = false;
fields.forEach(function (field) {
switch (field.name) {
case 'Title': {
if (field.value === "") {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Identifier': {
if (field.value === "") {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Short Description': {
if (field.value === "") {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Description': {
if (field.value === "") {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Banner': {
if (field.value.length === 0) {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Icon': {
if (field.value.length === 0) {
errors[field.name] = field.name + " is required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
case 'Screenshots': {
if (field.value.length < 3) {
errors[field.name] = "3 " + field.name + " are required!";
errorsPresent = true;
} else {
errorsPresent = false;
}
break;
}
}
});
if (!errorsPresent) {
this.setStepData();
} else {
this.setState({errors: errors}, console.log(errors));
}
}
/** /**
* Creates an object with the current step data and persist in the parent. * Creates an object with the current step data and persist in the parent.
* */ * */
setStepData() { setStepData() {
let stepData = { let stepData = {
icon: this.state.icon, icon: this.state.icon,
name: this.state.name,
tags: this.state.tags,
banner: this.state.banner, banner: this.state.banner,
category: this.categories[this.state.category], screenshots: this.state.screenshots
identifier: this.state.identifier,
screenshots: this.state.screenshots,
description: this.state.description,
shortDescription: this.state.shortDescription
}; };
this.props.setData("step2", {step: stepData}); this.props.setData("step2", {step: stepData});
}; };
/**
* Set text field values to state.
* */
onTextFieldChange(event, value) {
let field = event.target.id;
switch (field) {
case "name": {
this.setState({name: value});
break;
}
case "shortDescription": {
this.setState({shortDescription: value});
break;
}
case "description": {
this.setState({description: value});
break;
}
case "identifier": {
this.setState({identifier: value});
break;
}
}
};
/** /**
* Removed user uploaded banner. * Removed user uploaded banner.
* */ * */
removeBanner(event, d) { removeBanner(event, d) {
console.log(event, d); console.log(event, d); //TODO: Remove this
this.setState({banner: []}); this.setState({banner: []});
}; };
@ -289,15 +102,13 @@ class Step3 extends Component {
* Removes selected screenshot. * Removes selected screenshot.
* */ * */
removeScreenshot(event) { removeScreenshot(event) {
console.log(event.target) console.log(event.target) //TODO: Remove this.
}; };
//TODO: Remove inline css.
render() { render() {
console.log(this.state.visibilityComponent);
return ( return (
<div className="createStep2Content"> <div className="createStep2Content">
<div>
<div>
<div> <div>
<FormGroup> <FormGroup>
<Label for="app-screenshots">Screenshots*</Label> <Label for="app-screenshots">Screenshots*</Label>
@ -310,18 +121,18 @@ class Step3 extends Component {
))} ))}
{this.state.screenshots.length < 3 ? {this.state.screenshots.length < 3 ?
<Dropzone <Dropzone
className="applicationCreateScreenshotDropZone" className="application-create-screenshot-dropzone"
accept="image/jpeg, image/png" accept="image/jpeg, image/png"
onDrop={(screenshots, rejected) => { onDrop={(screenshots, rejected) => {
let tmpScreenshots = this.state.screenshots; let tmpScreenshots = this.state.screenshots;
tmpScreenshots.push(screenshots); tmpScreenshots.push(screenshots);
console.log(screenshots); console.log(screenshots); //TODO: Remove this
this.setState({ this.setState({
screenshots: tmpScreenshots screenshots: tmpScreenshots
}); });
}} }}
> >
<p className="applicationCreateScreenshotp">+</p> <i className="fw fw-add"></i>
</Dropzone> : <div/>} </Dropzone> : <div/>}
</div> </div>
</FormGroup> </FormGroup>
@ -340,13 +151,13 @@ class Step3 extends Component {
{this.state.icon.length === 0 ? {this.state.icon.length === 0 ?
<Dropzone <Dropzone
className="applicationCreateIconDropZone" className="application-create-icon-dropzone"
accept="image/jpeg, image/png" accept="image/jpeg, image/png"
onDrop={(icon, rejected) => { onDrop={(icon, rejected) => {
this.setState({icon, rejected}); this.setState({icon, rejected});
}} }}
> >
<p className="applicationCreateIconp">+</p> <i className="fw fw-add"></i>
</Dropzone> : <div/>} </Dropzone> : <div/>}
</div> </div>
</FormGroup> </FormGroup>
@ -363,13 +174,13 @@ class Step3 extends Component {
))} ))}
{this.state.banner.length === 0 ? {this.state.banner.length === 0 ?
<Dropzone <Dropzone
className="applicationCreateBannerDropZone" className="application-create-banner-dropzone"
accept="image/jpeg, image/png" accept="image/jpeg, image/png"
onDrop={(banner, rejected) => { onDrop={(banner, rejected) => {
this.setState({banner, rejected}); this.setState({banner, rejected});
}} }}
> >
<p className="applicationCreateBannerp">+</p> <i className="fw fw-add"></i>
</Dropzone> : <div/> </Dropzone> : <div/>
} }
</div> </div>
@ -377,8 +188,6 @@ class Step3 extends Component {
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
); );
} }
} }

@ -38,8 +38,8 @@ import Switch from '../../../UIComponents/Switch/Switch'
* *
* Parent Component: Create * Parent Component: Create
* Props: * Props:
* * handleFinish : {type: function, Invokes handleNext function in Parent.} * * handleFinish : {type: function, Invokes onNextClick function in Parent.}
* * handlePrev : {type: function, Invokes handlePrev function in Parent} * * onPrevClick : {type: function, Invokes onPrevClick function in Parent}
* * setData : {type: function, Invokes setStepData function in Parent} * * setData : {type: function, Invokes setStepData function in Parent}
* * removeData : {type: Invokes removeStepData function in Parent} * * removeData : {type: Invokes removeStepData function in Parent}
* */ * */
@ -60,7 +60,7 @@ class Step4 extends Component {
/** /**
* Handles finish button click. * Handles finish button click.
* This invokes handleNext function in parent component. * This invokes onNextClick function in parent component.
* */ * */
handleFinish() { handleFinish() {
this.props.handleFinish(); this.props.handleFinish();

@ -16,10 +16,9 @@
* under the License. * under the License.
*/ */
import './baseLayout.css';
import {Col, Row} from "reactstrap"; import {Col, Row} from "reactstrap";
import React, {Component} from 'react'; import React, {Component} from 'react';
import GeneralInfo from "../GeneralInfo"; import GeneralInfo from "../GenenralInfo/GeneralInfo";
import ReleaseManager from '../../Release/ReleaseMgtBase/ReleaseManager'; import ReleaseManager from '../../Release/ReleaseMgtBase/ReleaseManager';
class ApplicationEdit extends Component { class ApplicationEdit extends Component {
@ -35,14 +34,12 @@ class ApplicationEdit extends Component {
} }
} }
handleClick(event) { handleTabClick(event) {
event.stopPropagation(); event.stopPropagation();
console.log(typeof event.target.value);
const key = event.target.value; const key = event.target.value;
switch (key) { switch (key) {
case "1": { case "1": {
console.log("Step1");
this.setState({activeTab: 1, general: "active", release: "", pkgmgt: ""}); this.setState({activeTab: 1, general: "active", release: "", pkgmgt: ""});
break; break;
} }
@ -74,24 +71,34 @@ class ApplicationEdit extends Component {
} }
} }
handleOnBackClick() {
window.location.href = "/publisher/assets/apps"
}
render() { render() {
console.log(this.state);
return ( return (
<div id="application-edit-base"> <div id="application-edit-base">
<Row id="application-edit-header"> <Row id="application-edit-header">
<Col>Application Name</Col> <Col xs="3">
<a className="back-to-app" onClick={this.handleOnBackClick.bind(this)}>
<i className="fw fw-left-arrow"></i>
</a>
</Col>
<Col>
Application Name
</Col>
</Row> </Row>
<Row id="application-edit-main-container"> <Row id="application-edit-main-container">
<Col xs="3"> <Col xs="3">
<div className="tab"> <div className="tab">
<button className={this.state.general} value={1} onClick={this.handleClick.bind(this)}> <button className={this.state.general} value={1} onClick={this.handleTabClick.bind(this)}>
General General
</button> </button>
<button className={this.state.release} value={2} onClick={this.handleClick.bind(this)}> <button className={this.state.release} value={2} onClick={this.handleTabClick.bind(this)}>
App App
Releases Releases
</button> </button>
<button className={this.state.pkgmgt} value={3} onClick={this.handleClick.bind(this)}> <button className={this.state.pkgmgt} value={3} onClick={this.handleTabClick.bind(this)}>
Package Manager Package Manager
</button> </button>
</div> </div>

@ -1,111 +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.
*/
#application-edit-base {
width: 70%;
margin: 0 auto;
height: 100%;
background-color: #f6f6f6;
border: solid 1px #828282;
}
#application-edit-header {
height: 50px;
width: 100%;
margin: 0;
background-color: #9a9a9a;
border: solid 1px #a2a2a2;
font-size: 20px;
}
.application-header-text {
margin: 10px 0px 0px 10px;
}
#save-btn-content {
float: right;
}
#app-save-btn {
border-radius: 0%;
}
.save-btn {
margin: 5px 5px 5px 0px;
height: 70%;
width: 50%;
float: right;
}
.save-btn:hover {
cursor: pointer;
}
/*Tab styling*/
div.tab {
float: left;
border: 1px solid #ccc;
background-color: #f1f1f1;
height: 100%;
}
/* Style the tab buttons */
div.tab button {
display: block;
background-color: inherit;
color: black;
padding: 15px 16px;
width: 100%;
border: none;
outline: none;
text-align: left;
cursor: pointer;
transition: 0.3s;
}
/* Change background color of buttons on hover */
div.tab button:hover {
background-color: #ddd;
cursor: pointer;
}
/* Create an active/current "tab button" class */
div.tab button.active {
background-color: #ccc;
}
#application-edit-main-container {
display: flex;
}
#application-edit-outer-content {
height: auto;
width: 100%;
}
#application-edit-content {
margin: 5px 10px 5px 10px;
width: 90%;
}
#app-edit-content {
height: 100%;
position: relative;
}

@ -0,0 +1,202 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React, {Component} from 'react';
import {Badge, Button, FormGroup, Input, Label, Row} from 'reactstrap';
import Dropzone from 'react-dropzone';
class GeneralInfo extends Component {
constructor() {
super();
this.state = {
defValue: "",
tags: [],
screenshots: [],
icon: [],
banner: []
}
}
//TODO: Remove Console logs.
render() {
return (
<div className="app-edit-general-info">
<Row>
<form>
<FormGroup>
<Label for="app-title">Title*</Label>
<Input
required
type="text"
name="appName"
id="app-title"
/>
</FormGroup>
<FormGroup>
<Label for="app-title">Description*</Label>
<Input
required
type="textarea"
multiline
name="appName"
id="app-title"
/>
</FormGroup>
<FormGroup>
<Label for="app-category">Category</Label>
<Input
type="select"
name="category"
id="app-category"
>
<option>Business</option>
</Input>
</FormGroup>
<FormGroup>
<Label for="app-visibility">Visibility</Label>
<Input
type="select"
name="visibility"
id="app-visibility"
>
<option>Devices</option>
<option>Roles</option>
<option>Groups</option>
</Input>
</FormGroup>
<FormGroup>
<Label for="app-tags">Tags*</Label>
<Input
required
type="text"
value={this.state.defValue}
name="app-tags"
id="app-tags"
/>
<div id="batch-content">
{this.state.tags.map(tag => {
return (
<Badge
style={{margin: '0 2px 0 2px'}}
value={tag.value}
>
{tag.value}
</Badge>
)
}
)}
</div>
</FormGroup>
<div>
<FormGroup>
<Label for="app-screenshots">Screenshots*</Label>
<span className="image-sub-title"> (600 X 800 32 bit PNG)</span>
<div id="screenshot-container">
{this.state.screenshots.map((tile) => (
<button id="img-btn-screenshot" style={{height: '210px', width: '410px'}}
onMouseEnter={() => {
console.log("Mouse Entered")
}}>
{console.log(tile[0].preview)}
<img style={{height: '200px', width: '400px'}} src={tile[0].preview}/>
</button>
))}
{this.state.screenshots.length < 3 ?
<Dropzone
className="application-create-screenshot-dropzone"
accept="image/jpeg, image/png"
onDrop={(screenshots, rejected) => {
let tmpScreenshots = this.state.screenshots;
tmpScreenshots.push(screenshots);
console.log(screenshots);
this.setState({
screenshots: tmpScreenshots
});
}}
>
<i className="fw fw-add"></i>
</Dropzone> : <div/>}
</div>
</FormGroup>
</div>
<div style={{display: 'flex'}}>
<div style={{float: 'left', marginRight: '15px'}}>
<FormGroup>
<Label for="app-icon">Icon*</Label>
<span className="image-sub-title"> (512 X 512 32 bit PNG)</span>
<div id="app-icon-container">
{this.state.icon.map((tile) => (
<button onMouseEnter={() => {
console.log("Mouse Entered")
}}>
<img style={{height: '200px', width: '200px'}} src={tile.preview}/>
</button>
))}
{this.state.icon.length === 0 ?
<Dropzone
className="application-create-icon-dropzone"
accept="image/jpeg, image/png"
onDrop={(icon, rejected) => {
this.setState({icon, rejected});
}}
>
<i className="fw fw-add"></i>
</Dropzone> : <div/>}
</div>
</FormGroup>
</div>
<div style={{marginLeft: '15px'}}>
<FormGroup>
<Label for="app-banner">Banner*</Label>
<span className="image-sub-title"> (1000 X 400 32 bit PNG)</span>
<div id="app-banner-container">
{this.state.banner.map((tile) => (
<button onMouseEnter={() => {
console.log("Mouse Entered")
}}>
<img style={{height: '200px', width: '400px'}} src={tile.preview}/>
</button>
))}
{this.state.banner.length === 0 ?
<Dropzone
className="application-create-banner-dropzone"
accept="image/jpeg, image/png"
onDrop={(banner, rejected) => {
this.setState({banner, rejected});
}}
>
<i className="fw fw-add"></i>
</Dropzone> : <div/>
}
</div>
</FormGroup>
</div>
</div>
<div className="save-info">
<Button>Save</Button>
</div>
</form>
</Row>
</div>
)
}
}
export default GeneralInfo;

@ -1,200 +0,0 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React, {Component} from 'react';
import {Badge, Button, FormGroup, Input, Label} from 'reactstrap';
import Dropzone from 'react-dropzone';
import './generalInfo.css';
class GeneralInfo extends Component {
constructor() {
super();
this.state = {
defValue: "",
tags: [],
screenshots: [],
icon: [],
banner: []
}
}
render() {
return (
<div className="app-edit-general-info">
<form>
<FormGroup>
<Label for="app-title">Title*</Label>
<Input
required
type="text"
name="appName"
id="app-title"
/>
</FormGroup>
<FormGroup>
<Label for="app-title">Description*</Label>
<Input
required
type="textarea"
multiline
name="appName"
id="app-title"
/>
</FormGroup>
<FormGroup>
<Label for="app-category">Category</Label>
<Input
type="select"
name="category"
id="app-category"
>
<option>Business</option>
</Input>
</FormGroup>
<FormGroup>
<Label for="app-visibility">Visibility</Label>
<Input
type="select"
name="visibility"
id="app-visibility"
>
<option>Devices</option>
<option>Roles</option>
<option>Groups</option>
</Input>
</FormGroup>
<FormGroup>
<Label for="app-tags">Tags*</Label>
<Input
required
type="text"
value={this.state.defValue}
name="app-tags"
id="app-tags"
/>
<div id="batch-content">
{this.state.tags.map(tag => {
return (
<Badge
style={{margin: '0 2px 0 2px'}}
value={tag.value}
>
{tag.value}
</Badge>
)
}
)}
</div>
</FormGroup>
<div>
<FormGroup>
<Label for="app-screenshots">Screenshots*</Label>
<span className="image-sub-title"> (600 X 800 32 bit PNG)</span>
<div id="screenshot-container">
{this.state.screenshots.map((tile) => (
<button id="img-btn-screenshot" style={{height: '210px', width: '410px'}}
onMouseEnter={() => {
console.log("Mouse Entered")
}}>
{console.log(tile[0].preview)}
<img style={{height: '200px', width: '400px'}} src={tile[0].preview}/>
</button>
))}
{this.state.screenshots.length < 3 ?
<Dropzone
className="applicationCreateScreenshotDropZone"
accept="image/jpeg, image/png"
onDrop={(screenshots, rejected) => {
let tmpScreenshots = this.state.screenshots;
tmpScreenshots.push(screenshots);
console.log(screenshots);
this.setState({
screenshots: tmpScreenshots
});
}}
>
<p className="applicationCreateScreenshotp">+</p>
</Dropzone> : <div/>}
</div>
</FormGroup>
</div>
<div style={{display: 'flex'}}>
<div style={{float: 'left', marginRight: '15px'}}>
<FormGroup>
<Label for="app-icon">Icon*</Label>
<span className="image-sub-title"> (512 X 512 32 bit PNG)</span>
<div id="app-icon-container">
{this.state.icon.map((tile) => (
<button onMouseEnter={() => {
console.log("Mouse Entered")
}}>
<img style={{height: '200px', width: '200px'}} src={tile.preview}/>
</button>
))}
{this.state.icon.length === 0 ?
<Dropzone
className="applicationCreateIconDropZone"
accept="image/jpeg, image/png"
onDrop={(icon, rejected) => {
this.setState({icon, rejected});
}}
>
<p className="applicationCreateIconp">+</p>
</Dropzone> : <div/>}
</div>
</FormGroup>
</div>
<div style={{marginLeft: '15px'}}>
<FormGroup>
<Label for="app-banner">Banner*</Label>
<span className="image-sub-title"> (1000 X 400 32 bit PNG)</span>
<div id="app-banner-container">
{this.state.banner.map((tile) => (
<button onMouseEnter={() => {
console.log("Mouse Entered")
}}>
<img style={{height: '200px', width: '400px'}} src={tile.preview}/>
</button>
))}
{this.state.banner.length === 0 ?
<Dropzone
className="applicationCreateBannerDropZone"
accept="image/jpeg, image/png"
onDrop={(banner, rejected) => {
this.setState({banner, rejected});
}}
>
<p className="applicationCreateBannerp">+</p>
</Dropzone> : <div/>
}
</div>
</FormGroup>
</div>
</div>
<div className="save-info">
<Button>Save</Button>
</div>
</form>
</div>
)
}
}
export default GeneralInfo;

@ -1,26 +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.
*/
.app-edit-general-info {
margin-top: 20px;
}
.save-info {
float: right;
margin-bottom: 10px;
}

@ -18,7 +18,6 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import './createRelease.css';
import {Button, FormGroup, FormText, Input, Label, Row} from "reactstrap"; import {Button, FormGroup, FormText, Input, Label, Row} from "reactstrap";
import UploadPackage from "./UploadPackage"; import UploadPackage from "./UploadPackage";
@ -27,8 +26,8 @@ class CreateRelease extends Component {
super(); super();
this.onTestMethodChange = this.onTestMethodChange.bind(this); this.onTestMethodChange = this.onTestMethodChange.bind(this);
this.showUploadArtifacts = this.showUploadArtifacts.bind(this); this.showUploadArtifacts = this.showUploadArtifacts.bind(this);
this.handleBack = this.handleBack.bind(this); this.onBackClick = this.onBackClick.bind(this);
this.backToRelease = this.backToRelease.bind(this); this.onBackToRelease = this.onBackToRelease.bind(this);
this.state = { this.state = {
open: true, open: true,
hiddenMain: false hiddenMain: false
@ -48,11 +47,11 @@ class CreateRelease extends Component {
this.setState({hiddenMain: true}) this.setState({hiddenMain: true})
} }
handleBack() { onBackClick() {
this.props.handleBack(); this.props.handleBack();
} }
backToRelease() { onBackToRelease() {
this.setState({hiddenMain: false}); this.setState({hiddenMain: false});
} }
@ -65,7 +64,7 @@ class CreateRelease extends Component {
{this.state.hiddenMain ? {this.state.hiddenMain ?
<div> <div>
<UploadPackage <UploadPackage
backToRelease={this.backToRelease} backToRelease={this.onBackToRelease}
selectedChannel={channel} selectedChannel={channel}
/> />
</div> : </div> :
@ -73,7 +72,7 @@ class CreateRelease extends Component {
<div> <div>
<Row> <Row>
<div className="release-header"> <div className="release-header">
<a onClick={this.handleBack}>{"<-"}</a> <a onClick={this.onBackClick}>{"<-"}</a>
<span id="create-release-header"> <span id="create-release-header">
<strong>{channel} Release</strong> <strong>{channel} Release</strong>
</span> </span>

@ -18,7 +18,6 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import './createRelease.css';
import {Button, Col, FormGroup, Input, Label, Row} from "reactstrap"; import {Button, Col, FormGroup, Input, Label, Row} from "reactstrap";
class UploadPackage extends Component { class UploadPackage extends Component {
@ -29,7 +28,7 @@ class UploadPackage extends Component {
} }
handleBack() { handleBack() {
this.props.backToRelease(); this.props.onBackToRelease();
} }
render() { render() {

@ -1,38 +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.
*/
.release-header {
margin-top: 20px;
margin-bottom: 20px;
}
.release-create {
height: 150px;
margin-bottom: 20px;
}
.release-detail-content {
width: 100%;
margin-top: 20%;
height: 300px;
}
.form-btn {
float: right;
margin-bottom: 10px;
}

@ -18,7 +18,6 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, {Component} from 'react'; import React, {Component} from 'react';
import './release-mgt.css';
import {Button, Col, Row} from "reactstrap"; import {Button, Col, Row} from "reactstrap";
import CreateRelease from "../Create/CreateRelease"; import CreateRelease from "../Create/CreateRelease";
@ -27,20 +26,20 @@ class ReleaseManager extends Component {
constructor() { constructor() {
super(); super();
this.getNoReleaseContent = this.getNoReleaseContent.bind(this); this.getNoReleaseContent = this.getNoReleaseContent.bind(this);
this.createRelease = this.createRelease.bind(this); this.onCreateRelease = this.onCreateRelease.bind(this);
this.handleBackPress = this.handleBackPress.bind(this); this.onBackClick = this.onBackClick.bind(this);
this.state = { this.state = {
createRelease: false, createRelease: false,
onGoing: "" onGoing: ""
} }
} }
createRelease(event) { onCreateRelease(event) {
event.preventDefault(); event.preventDefault();
this.setState({createRelease: true, onGoing: event.target.value}) this.setState({createRelease: true, onGoing: event.target.value})
} }
handleBackPress() { onBackClick() {
this.setState({createRelease: false}); this.setState({createRelease: false});
} }
@ -61,7 +60,7 @@ class ReleaseManager extends Component {
className="button-add" className="button-add"
id={release.toLowerCase()} id={release.toLowerCase()}
value={release} value={release}
onClick={this.createRelease} onClick={this.onCreateRelease}
> >
Create a Release Create a Release
</Button> </Button>
@ -77,7 +76,7 @@ class ReleaseManager extends Component {
{this.state.createRelease ? {this.state.createRelease ?
<CreateRelease <CreateRelease
channel={this.state.onGoing} channel={this.state.onGoing}
handleBack={this.handleBackPress} handleBack={this.onBackClick}
/> : /> :
<div id="release-mgt-content"> <div id="release-mgt-content">
<Row> <Row>

@ -19,7 +19,6 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import {withRouter} from 'react-router-dom'; import {withRouter} from 'react-router-dom';
import {Col, Row} from "reactstrap"; import {Col, Row} from "reactstrap";
import './applicationView.css';
/** /**
* Application view component. * Application view component.
@ -76,8 +75,15 @@ class ApplicationView extends Component {
</Col> </Col>
</Row> </Row>
<Row> <Row>
<Col>Rating</Col> <Col>
<Col>View in Store</Col> <i className="fw fw-star"></i>
<i className="fw fw-star"></i>
<i className="fw fw-star"></i>
<i className="fw fw-star"></i>
</Col>
<Col>
<a href="#">View in Store</a>
</Col>
</Row> </Row>
</div> </div>
<hr/> <hr/>

@ -16,7 +16,6 @@
* under the License. * under the License.
*/ */
import Theme from '../../theme';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Chip from 'material-ui/Chip'; import Chip from 'material-ui/Chip';
import Dropzone from 'react-dropzone'; import Dropzone from 'react-dropzone';
@ -79,18 +78,6 @@ class PlatformCreate extends Component {
{key: 2, value: 'Boolean'}, {key: 2, value: 'Boolean'},
{key: 3, value: 'File'}] {key: 3, value: 'File'}]
}; };
this.scriptId = "platform-create";
}
componentWillMount() {
/**
*Loading the theme files based on the the user-preference.
*/
Theme.insertThemingScripts(this.scriptId);
}
componentWillUnmount() {
Theme.removeThemingScripts(this.scriptId);
} }
/** /**

@ -16,7 +16,6 @@
* under the License. * under the License.
*/ */
import Theme from '../../theme';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {withRouter} from 'react-router-dom'; import {withRouter} from 'react-router-dom';
import TextField from 'material-ui/TextField'; import TextField from 'material-ui/TextField';
@ -41,7 +40,6 @@ class PlatformListing extends Component {
platforms: [], platforms: [],
asc: true asc: true
}; };
this.scriptId = "platform-listing";
} }
headers = [ headers = [
@ -72,17 +70,6 @@ class PlatformListing extends Component {
} }
]; ];
componentWillMount() {
/**
*Loading the theme files based on the the user-preference.
*/
Theme.insertThemingScripts(this.scriptId);
}
componentWillUnmount() {
Theme.removeThemingScripts(this.scriptId);
}
componentDidMount() { componentDidMount() {
let platformsPromise = PlatformMgtApi.getPlatforms(); let platformsPromise = PlatformMgtApi.getPlatforms();
platformsPromise.then( platformsPromise.then(

@ -42,7 +42,7 @@ class Drawer extends Component {
return ( return (
<div> <div>
<div id="app-view" className="app-view-drawer" style={this.props.style}> <div id="app-view" className="app-view-drawer" style={this.props.style}>
<a onClick={this.closeDrawer} className="drawer-close-btn">&times;</a> <a onClick={this.closeDrawer} className="drawer-close-btn"><i className="fw fw-uncheck"></i></a>
{this.props.children} {this.props.children}
</div> </div>
</div> </div>

@ -21,13 +21,12 @@
width: 0; /* 0 width - change this with JavaScript */ width: 0; /* 0 width - change this with JavaScript */
position: fixed; /* Stay in place */ position: fixed; /* Stay in place */
z-index: 1; /* Stay on top */ z-index: 1; /* Stay on top */
top: 5%; top: 8%;
right: 0%; right: 0%;
background-color: #b5b5b5; background-color: #ffffff;
overflow-x: hidden; /* Disable horizontal scroll */ overflow-x: hidden; /* Disable horizontal scroll */
padding-top: 60px; /* Place content 60px from the top */ padding-top: 60px; /* Place content 60px from the top */
transition: 0.5s; /* 0.5 second transition effect to slide in the sidenav */ transition: 0.5s; /* 0.5 second transition effect to slide in the sidenav */
border: solid 1px black;
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
} }

@ -16,41 +16,32 @@
* under the License. * under the License.
*/ */
import PropTypes from 'prop-types';
#application-view-content { import React, {Component} from 'react';
width: 100%; import './floatingButton.css';
}
/**
#application-view-row { * Floating Action button.
margin: 10px 10px 20px 20px; * */
} class FloatingButton extends Component {
#app-icon { handleClick(event) {
height: 100px; this.props.onClick(event);
width: 100px; }
border: solid 1px black;
border-radius: 50%; render() {
} let classes = 'btn-circle ' + this.props.className;
return (
.app-updated-date { <div className={classes} onClick={this.handleClick.bind(this)}>
color: #888888; <i className="fw fw-add"></i>
font-style: italic; </div>
} )
}
.app-install-count { }
font-style: italic;
} FloatingButton.propTypes = {
classNames: PropTypes.string,
.app-details-tbl { onClick: PropTypes.func
outline: none; };
border-color: #2196F3;
} export default FloatingButton;
.app-details-tbl tr {
margin: 20px 0 0 0;
}
.app-details-tbl td {
margin-left: 10px;
max-width: 400px;
}

@ -16,35 +16,35 @@
* under the License. * under the License.
*/ */
.release-content { .btn-circle {
height: 180px; color: white;
width: 95%;
border: dashed 1px #626262;
border-radius: 2%;
position: relative; position: relative;
background-color: #e8e8e8; background-color: #e65100;
border-radius: 50%;
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
} }
.release-content:after { .btn-circle i {
content: ""; position: absolute;
letter-spacing: 4px; margin-top: 37%;
margin-left: 37%;
} }
.release { .small {
margin: 30px 10px 20px 30px; height: 50px;
width: 50px;
} }
.no-release-content { .medium {
position: absolute; height: 100px;
margin-top: 10px; width: 100px;
left: 40%;
} }
.button-add:hover { .btn-circle:hover {
cursor: pointer; cursor: pointer;
background-color: rgb(255, 93, 2);
} }
.release-inner { .primary {
margin-top: 5%; background-color: blue;
} }

@ -16,10 +16,11 @@
* under the License. * under the License.
*/ */
import qs from 'qs';
import React, {Component} from 'react'; import React, {Component} from 'react';
import {Redirect, Switch} from 'react-router-dom'; import {Redirect, Switch} from 'react-router-dom';
import AuthHandler from '../../../api/authHandler'; import AuthHandler from '../../../api/authHandler';
import {Button, Card, CardBlock, CardSubtitle, CardTitle, Col, Form, FormGroup, Input, Label} from 'reactstrap'; import {Button, Card, CardBlock, CardTitle, Col, Form, FormGroup, Input, Label} from 'reactstrap';
/** /**
* The Login Component. * The Login Component.
@ -42,20 +43,15 @@ class Login extends Component {
} }
} }
componentWillMount() {
console.log("IN Login")
}
componentDidMount() { componentDidMount() {
console.log("in Login") let queryString = this.props.location.search;
// let queryString = this.props.location.search; console.log(queryString);
// console.log(queryString); queryString = queryString.replace(/^\?/, '');
// queryString = queryString.replace(/^\?/, ''); /* With QS version up we can directly use {ignoreQueryPrefix: true} option */
// /* With QS version up we can directly use {ignoreQueryPrefix: true} option */ let params = qs.parse(queryString);
// let params = qs.parse(queryString); if (params.referrer) {
// if (params.referrer) { this.setState({referrer: params.referrer});
// this.setState({referrer: params.referrer}); }
// }
} }
handleLogin(event) { handleLogin(event) {
@ -141,19 +137,21 @@ class Login extends Component {
<FormGroup row> <FormGroup row>
<Label for="userName" sm={2}>User Name:</Label> <Label for="userName" sm={2}>User Name:</Label>
<Col sm={10}> <Col sm={10}>
<Input type="text" name="userName" id="userName" placeholder="User Name" onChange={this.onUserNameChange.bind(this)}/> <Input type="text" name="userName" id="userName" placeholder="User Name"
onChange={this.onUserNameChange.bind(this)}/>
</Col> </Col>
</FormGroup> </FormGroup>
<FormGroup row> <FormGroup row>
<Label for="password" sm={2}>Password:</Label> <Label for="password" sm={2}>Password:</Label>
<Col sm={10}> <Col sm={10}>
<Input type="password" name="text" id="password" placeholder="Password" onChange={this.onPasswordChange.bind(this)}/> <Input type="password" name="text" id="password" placeholder="Password"
onChange={this.onPasswordChange.bind(this)}/>
</Col> </Col>
</FormGroup> </FormGroup>
<FormGroup check row> <FormGroup check row>
<Col sm={{ size: 10, offset: 2 }}> <Col sm={{size: 10, offset: 2}}>
<Button type="submit" id="login-btn">Submit</Button> <Button type="submit" id="login-btn">Login</Button>
</Col> </Col>
</FormGroup> </FormGroup>
</Form> </Form>

@ -1,238 +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.
*/
body {
width: 100%;
font-family: sans-serif;
}
#userName {
border-radius: 0;
}
#password {
border-radius: 0;
}
#login-btn {
border-radius: 0;
background-color: navy;
color: white;
cursor: pointer;
}
#login-container {
width: 50%;
margin: 0 auto
}
#login-card {
border-radius: 0;
background-color: #BaBaBa;
}
#container {
background-color: #ffffff;
}
#header-content {
height: 100px;
width: 100%;
margin: 0 10px 0 0;
background-color: #BDBDBD;
border-bottom: solid 2px;
position: fixed; /* Set the navbar to fixed position */
top: 0; /* Position the navbar at the top of the page */
z-index: 2;
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
#application-content {
max-height: 800px;
margin-top: 150px;
}
#add-btn {
border-radius: 50%;
border: solid 2px;
position: absolute;
background-color: #BDBDBD;
left: 15px;
top: 75px;
cursor: pointer;
height: 50px;
width: 50px;
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}
.add-btn.div {
position: relative;
margin-top: 20px;
margin-left: 20px;
}
#fw-api:before {
content: '\e601';
}
#btn {
background-color: #BDBDBD;
border-color: #BDBDBD;
}
#header-text {
font-size: 25px;
top: 10px;
margin-left: 10px;
}
#header-btn {
float: right;
}
#search-box {
float: right;
}
#search {
background-color: #BDBDBD;
left: 110px;
top: 20px;
height: 25px;
outline: none;
border: none;
border-bottom: solid 1px black;
border-radius: 0%;
}
#application-list {
margin-top: 20px;
transition: margin-right .5s;
}
#app-image-screenshot {
width: 300px;
height: 300px;
}
#app-image-icon {
width: 300px;
height: 300px;
}
#app-image-banner {
width: 400px;
height: 300px;
}
.applicationCreateBannerDropZone {
width: 300px;
height: 150px;
border-radius: 5%;
background-color: rgba(157, 159, 157, 0.53);
border: dashed #888888 2px;
}
.applicationCreateBannerp {
margin: 70px 40px 40px 150px;
}
.applicationCreateScreenshotDropZone {
width: 150px;
height: 150px;
margin: 0 5px 0 5px;
border-radius: 10%;
background-color: rgba(157, 159, 157, 0.53);
border: dashed #888888 2px;
}
.applicationCreateIconDropZone {
width: 150px;
height: 150px;
border-radius: 10%;
background-color: rgba(157, 159, 157, 0.53);
border: dashed #888888 2px;
}
.applicationCreateIconp {
margin: 70px 40px 70px 70px;
}
.applicationCreateScreenshotp {
margin: 70px 40px 70px 70px;
}
#screenshot-container {
display: flex;
overflow-x: auto;
height: 200px;
}
#app-icon-container {
height: 300px;
overflow-x: auto;
}
#modal-body-content {
max-height: 700px;
overflow-y: auto;
}
#img-btn-screenshot {
margin: 0 5px 0 5px;
}
#app-create-modal {
max-width: 700px;
overflow-x: auto;
}
#store {
border: none;
border-bottom: solid #BDBDBD 1px;
border-radius: 0px;
width: 200px;
}
#version {
border: none;
border-bottom: solid #BDBDBD 1px;
border-radius: 0px;
width: 200px;
}
#app-release-switch-content {
display: flex;
}
#app-release-switch-label {
position: absolute;
float: left;
}
#app-release-switch-switch {
position: absolute;
right: 10px;
}
.image-sub-title {
font-style: italic;
font-size: 12px;
color: #818181;
}

@ -16,7 +16,6 @@
* under the License. * under the License.
*/ */
import './index.css';
import React from 'react'; import React from 'react';
import Publisher from './App'; import Publisher from './App';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';

@ -48,6 +48,10 @@ const config = {
test: /\.css$/, test: /\.css$/,
use: [ 'style-loader', 'css-loader' ] use: [ 'style-loader', 'css-loader' ]
}, },
{
test: /\.scss$/,
use: [ 'style-loader', 'scss-loader' ]
},
{ {
test: /\.less$/, test: /\.less$/,
use: [{ use: [{

Loading…
Cancel
Save