forked from community/device-mgt-core
parent
485ff83fc2
commit
498b2c02aa
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
"es2015"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"theme": {
|
||||||
|
"type": "default",
|
||||||
|
"value": "lightBaseTheme"
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 443 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 1.9 KiB |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.image-container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
opacity: 1;
|
||||||
|
display: block;
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
height: auto;
|
||||||
|
transition: .5s ease;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-content {
|
||||||
|
transition: .5s ease;
|
||||||
|
opacity: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
background-color: rgba(243, 243, 243, 0.43);
|
||||||
|
border-radius: 50%;
|
||||||
|
border: solid 1px #ffffff;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
-ms-transform: translate(-50%, -50%)
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container:hover .image {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-container:hover .btn-content {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
color: #000000;
|
||||||
|
font-size: 16px;
|
||||||
|
padding: 20px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.chip {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0 25px;
|
||||||
|
height: 50px;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 50px;
|
||||||
|
border-radius: 25px;
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chip img {
|
||||||
|
float: left;
|
||||||
|
margin: 0 10px 0 -25px;
|
||||||
|
height: 50px;
|
||||||
|
width: 50px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
padding-left: 10px;
|
||||||
|
color: #888;
|
||||||
|
font-weight: bold;
|
||||||
|
float: right;
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn:hover {
|
||||||
|
color: #000;
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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-view-drawer {
|
||||||
|
height: 100%; /* 100% Full-height */
|
||||||
|
width: 0; /* 0 width - change this with JavaScript */
|
||||||
|
position: fixed; /* Stay in place */
|
||||||
|
z-index: 1; /* Stay on top */
|
||||||
|
top: 8%;
|
||||||
|
right: 0%;
|
||||||
|
background-color: #ffffff;
|
||||||
|
overflow-x: hidden; /* Disable horizontal scroll */
|
||||||
|
padding-top: 60px; /* Place content 60px from the top */
|
||||||
|
transition: 0.5s; /* 0.5 second transition effect to slide in the sidenav */
|
||||||
|
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
||||||
|
|
||||||
|
.app-view-drawer a {
|
||||||
|
padding: 8px 8px 8px 32px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 25px;
|
||||||
|
color: #818181;
|
||||||
|
display: block;
|
||||||
|
transition: 0.3s
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Position and style the close button (top right corner) */
|
||||||
|
.app-view-drawer .closebtn {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 25px;
|
||||||
|
font-size: 36px;
|
||||||
|
margin-left: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-close-btn {
|
||||||
|
height: 40px;
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-close-btn:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #818181;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style page content - use this if you want to push the page content to the right when you open the side navigation */
|
||||||
|
#main {
|
||||||
|
transition: margin-left .5s;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
|
||||||
|
@media screen and (max-height: 450px) {
|
||||||
|
.sidenav {padding-top: 15px;}
|
||||||
|
.sidenav a {font-size: 18px;}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.btn-circle {
|
||||||
|
color: white;
|
||||||
|
position: relative;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-circle i {
|
||||||
|
position: absolute;
|
||||||
|
margin-top: 37%;
|
||||||
|
margin-left: 37%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small {
|
||||||
|
height: 50px;
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.medium {
|
||||||
|
height: 100px;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-circle:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: rgb(255, 93, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary {
|
||||||
|
background-color: blue;
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.notification-app-icon {
|
||||||
|
border-radius: 50%;
|
||||||
|
border: solid 1px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small {
|
||||||
|
height: 50px;
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.medium {
|
||||||
|
height: 100px;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#notification-view-content {
|
||||||
|
width: 50%;
|
||||||
|
border: solid 1px black;
|
||||||
|
margin: 0 auto;
|
||||||
|
box-shadow: -2px 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||||
|
}
|
||||||
|
|
||||||
|
#notification-content {
|
||||||
|
margin: 20px 10px 20px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app-reject-msg {
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
background-color: #888888;
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* The switch - the box around the slider */
|
||||||
|
.switch {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 40px;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide default HTML checkbox */
|
||||||
|
.switch input {display:none;}
|
||||||
|
|
||||||
|
/* The slider */
|
||||||
|
.slider {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #ccc;
|
||||||
|
-webkit-transition: .4s;
|
||||||
|
transition: .4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider:before {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
height: 16px;
|
||||||
|
width: 16px;
|
||||||
|
left: 4px;
|
||||||
|
bottom: 4px;
|
||||||
|
background-color: white;
|
||||||
|
-webkit-transition: .4s;
|
||||||
|
transition: .4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked + .slider {
|
||||||
|
background-color: #2196F3;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus + .slider {
|
||||||
|
box-shadow: 0 0 1px #2196F3;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked + .slider:before {
|
||||||
|
-webkit-transform: translateX(16px);
|
||||||
|
-ms-transform: translateX(16px);
|
||||||
|
transform: translateX(16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rounded sliders */
|
||||||
|
.slider.round {
|
||||||
|
border-radius: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider.round:before {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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 from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
it('renders without crashing', () => {
|
||||||
|
const div = document.createElement('div');
|
||||||
|
ReactDOM.render(<App />, div);
|
||||||
|
});
|
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import Axios from 'axios';
|
||||||
|
import AuthHandler from './authHandler';
|
||||||
|
import Constants from '../common/constants';
|
||||||
|
import Helper from './helpers/appMgtApiHelpers';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api definitions related to application management.
|
||||||
|
* TODO: Work to be done on Application release.
|
||||||
|
* */
|
||||||
|
export default class ApplicationMgtApi {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api for create an application.
|
||||||
|
* @param: applicationData: The application data object. This contains an object array of each step data from
|
||||||
|
* application creation wizard.
|
||||||
|
*
|
||||||
|
* From applicationData, the proper application object will be created and send it to the api.
|
||||||
|
* */
|
||||||
|
static createApplication(applicationData) {
|
||||||
|
let {application, images} = Helper.buildApplication(applicationData);
|
||||||
|
const headers = AuthHandler.createAuthenticationHeaders("application/json");
|
||||||
|
console.log(application);
|
||||||
|
console.log(images);
|
||||||
|
Axios.post(Constants.appManagerEndpoints.CREATE_APP, application, {headers: headers});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload the image artifacts (banner, icon, screenshots) related to the application.
|
||||||
|
* @param appId: The application uuid of the application which the images should be uploaded to.
|
||||||
|
* @param images: The images object. This contains icon, banner and screenshots.
|
||||||
|
* */
|
||||||
|
static uploadImageArtifacts(appId, images) {
|
||||||
|
let formData = new FormData();
|
||||||
|
formData.append('icon', images.icon);
|
||||||
|
formData.append('banner', images.banner);
|
||||||
|
formData.append('screenshot', images.screenshots);
|
||||||
|
console.log("Image", formData);
|
||||||
|
const headers = AuthHandler.createAuthenticationHeaders("multipart/form-data");
|
||||||
|
return Axios.post(Constants.appManagerEndpoints.UPLOAD_IMAGE_ARTIFACTS + appId, formData, {headers: headers});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to handle application release process.
|
||||||
|
* */
|
||||||
|
static releaseApplication(appId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Promote the current life cycle state of the application.
|
||||||
|
* @param appId: The uuid of the application which the state should be updated.
|
||||||
|
* @param nextState: The next lifecycle state that the application can be updated to.
|
||||||
|
*
|
||||||
|
* URL Pattern : /application/1.0/
|
||||||
|
* */
|
||||||
|
static updateLifeCycleState(appId, nextState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next possible state, which the application can be promoted to.
|
||||||
|
* @param appId: The application uuid.
|
||||||
|
*/
|
||||||
|
static getNextLifeCycleState(appId) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit created application.
|
||||||
|
* @param applicationData: The modified application data.
|
||||||
|
* */
|
||||||
|
static editApplication(applicationData) {
|
||||||
|
let app = Helper.buildApplication(applicationData).application;
|
||||||
|
const headers = AuthHandler.createAuthenticationHeaders("application/json");
|
||||||
|
return Axios.put(Constants.appManagerEndpoints.CREATE_APP, app, {headers: headers});
|
||||||
|
}
|
||||||
|
|
||||||
|
static getApplicationArtifacts(appId, artifactName) {
|
||||||
|
const headers = AuthHandler.createAuthenticationHeaders("image/png");
|
||||||
|
return Axios.get(Constants.appManagerEndpoints.GET_IMAGE_ARTIFACTS + appId + "?name=" + artifactName,
|
||||||
|
{headers: headers});
|
||||||
|
}
|
||||||
|
|
||||||
|
static editApplicationArtifacts(appId, images) {
|
||||||
|
let formData = new FormData();
|
||||||
|
formData.append('icon', images.icon);
|
||||||
|
formData.append('banner', images.banner);
|
||||||
|
formData.append('screenshot', images.screenshots);
|
||||||
|
const headers = AuthHandler.createAuthenticationHeaders("application/json");
|
||||||
|
return Axios.put(Constants.appManagerEndpoints.UPLOAD_IMAGE_ARTIFACTS + appId, formData, {headers: headers});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all the created applications for the user.
|
||||||
|
* @return Object: The response object from the axios post.
|
||||||
|
* */
|
||||||
|
static getApplications() {
|
||||||
|
const headers = AuthHandler.createAuthenticationHeaders("application/json");
|
||||||
|
return Axios.get(Constants.appManagerEndpoints.GET_ALL_APPS, {headers: headers});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get specific application.
|
||||||
|
* @param appId: The application Id.
|
||||||
|
* */
|
||||||
|
static getApplication(appId) {
|
||||||
|
const headers = AuthHandler.createAuthenticationHeaders("application/json");
|
||||||
|
return Axios.get(Constants.appManagerEndpoints.GET_ALL_APPS + appId, {headers: headers});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete specified application.
|
||||||
|
* @param appId: The id of the application which is to be deleted.
|
||||||
|
* */
|
||||||
|
static deleteApplication(appId) {
|
||||||
|
const headers = AuthHandler.createAuthenticationHeaders("application/json");
|
||||||
|
return Axios.delete(Constants.appManagerEndpoints.GET_ALL_APPS + appId, {headers: headers});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import Axios from 'axios';
|
||||||
|
import User from './data/user';
|
||||||
|
import Utils from './data/utils';
|
||||||
|
import Constants from "../common/constants";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles all tasks related to Authentication and Authorization.
|
||||||
|
* Generate access tokens, verify the user has necessary permissions etc.
|
||||||
|
* */
|
||||||
|
class AuthHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a request to the auth handler endpoint (auth/application-mgt/v1.0/auth/login) and generate token pair.
|
||||||
|
* @param userName: The user name of the user.
|
||||||
|
* @param password: The user password.
|
||||||
|
* @return Object: The response object from the axios post.
|
||||||
|
* */
|
||||||
|
static login(userName, password) {
|
||||||
|
const headers = {"Content-type": "application/json"};
|
||||||
|
let login_promise =
|
||||||
|
Axios.post(Constants.userConstants.LOGIN_URL+"?userName=" + userName+ "&password=" + password,
|
||||||
|
null, {headers: headers});
|
||||||
|
|
||||||
|
login_promise.then(response => {
|
||||||
|
console.log(response);
|
||||||
|
const userName = response.data.userName;
|
||||||
|
const validityPeriod = response.data.expires_in; // In seconds
|
||||||
|
const WSO2_IOT_TOKEN = response.data.access_token;
|
||||||
|
const refreshToken = response.data.refresh_token;
|
||||||
|
const clientId = response.data.application_info[0].consumerKey;
|
||||||
|
const clientSecret = response.data.application_info[0].consumerSecret;
|
||||||
|
|
||||||
|
const user = new User(userName, clientId, clientSecret, validityPeriod);
|
||||||
|
console.log(user);
|
||||||
|
user.setAuthToken(WSO2_IOT_TOKEN, validityPeriod);
|
||||||
|
let expiresIn = Date.now() + (validityPeriod * 1000);
|
||||||
|
localStorage.setItem("expiresIn", expiresIn);
|
||||||
|
AuthHandler.setUser(user);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return login_promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persists the user object in browser's local storage.
|
||||||
|
* @param user: The user object.
|
||||||
|
* */
|
||||||
|
static setUser(user) {
|
||||||
|
if (!user instanceof User) {
|
||||||
|
throw "Invalid user object";
|
||||||
|
}
|
||||||
|
user.created = Date.now();
|
||||||
|
localStorage.setItem(Constants.userConstants.WSO2_USER, JSON.stringify(user.toJson()));
|
||||||
|
/* TODO: IMHO it's better to get this key (`wso2_user`) from configs */
|
||||||
|
}
|
||||||
|
|
||||||
|
static unauthorizedErrorHandler(error_response) {
|
||||||
|
if (error_response.status !== 401) { /* Skip unrelated response code to handle in unauthorizedErrorHandler*/
|
||||||
|
throw error_response;
|
||||||
|
/* re throwing the error since we don't handle it here and propagate to downstream error handlers in catch chain*/
|
||||||
|
}
|
||||||
|
let message = "The session has expired" + ".<br/> You will be redirect to the login page ...";
|
||||||
|
if (true) {
|
||||||
|
alert(message);
|
||||||
|
} else {
|
||||||
|
throw error_response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the logged in user.
|
||||||
|
* @return User: The logged in user object.
|
||||||
|
* */
|
||||||
|
static getUser() {
|
||||||
|
const userData = localStorage.getItem(Constants.userConstants.WSO2_USER);
|
||||||
|
const partialToken = Utils.getCookie(Constants.userConstants.PARTIAL_TOKEN);
|
||||||
|
|
||||||
|
if (!(userData && partialToken)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return User.fromJson(JSON.parse(userData));
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoggedIn() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static logout() {
|
||||||
|
const user = AuthHandler.getUser();
|
||||||
|
const clientId = user.getClientId();
|
||||||
|
const clientSecret = user.getClientSecret();
|
||||||
|
const token = user.getAuthToken();
|
||||||
|
const headers = {"Content-type": "application/json"};
|
||||||
|
|
||||||
|
let login_promise = Axios.post(Constants.userConstants.LOGOUT_URL+"?token=" + token + "&clientId=" + clientId
|
||||||
|
+ "&clientSecret=" + clientSecret,
|
||||||
|
null, {headers: headers});
|
||||||
|
login_promise.then(
|
||||||
|
(response) => {
|
||||||
|
Utils.delete_cookie(Constants.userConstants.PARTIAL_TOKEN);
|
||||||
|
localStorage.removeItem(Constants.userConstants.WSO2_USER);
|
||||||
|
window.location = "/";
|
||||||
|
}
|
||||||
|
).catch(
|
||||||
|
(err) => {
|
||||||
|
AuthHandler.unauthorizedErrorHandler(err);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the access token is expired.
|
||||||
|
* @return boolean: True if expired. False otherwise.
|
||||||
|
* */
|
||||||
|
static isTokenExpired() {
|
||||||
|
const expiresIn = localStorage.getItem("expiresIn");
|
||||||
|
return (expiresIn < Date.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
static createAuthenticationHeaders(contentType) {
|
||||||
|
if (AuthHandler.getUser().getAuthToken()) {
|
||||||
|
return {
|
||||||
|
"Authorization": "Bearer " + AuthHandler.getUser().getAuthToken(),
|
||||||
|
"Content-Type": contentType,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return "User not found";
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AuthHandler;
|
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
import Utils from './utils'
|
||||||
|
import Constants from '../../common/constants';
|
||||||
|
/**
|
||||||
|
* Represent an user logged in to the application, There will be allays one user per session and
|
||||||
|
* this user details will be persist in browser localstorage.
|
||||||
|
*/
|
||||||
|
export default class User {
|
||||||
|
constructor(name, clientId, clientSecret, validityPeriod) {
|
||||||
|
if (User._instance) {
|
||||||
|
return User._instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._userName = name;
|
||||||
|
this._clientId = clientId;
|
||||||
|
this._clientSecret = clientSecret;
|
||||||
|
this._expires = validityPeriod;
|
||||||
|
User._instance = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OAuth scopes which are available for use by this user
|
||||||
|
* @returns {Array} : An array of scopes
|
||||||
|
*/
|
||||||
|
get scopes() {
|
||||||
|
return this._scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set OAuth scopes available to be used by this user
|
||||||
|
* @param {Array} newScopes : An array of scopes
|
||||||
|
*/
|
||||||
|
set scopes(newScopes) {
|
||||||
|
Object.assign(this.scopes, newScopes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the JS accessible access token fragment from cookie storage.
|
||||||
|
* @returns {String|null}
|
||||||
|
*/
|
||||||
|
getAuthToken() {
|
||||||
|
return Utils.getCookie(Constants.userConstants.PARTIAL_TOKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
getClientId() {
|
||||||
|
return this._clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
getClientSecret() {
|
||||||
|
return this._clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the JavaScript accessible access token segment in cookie storage
|
||||||
|
* @param {String} newToken : Part of the access token which needs when accessing REST API
|
||||||
|
* @param {Number} validityPeriod : Validity period of the cookie in seconds
|
||||||
|
*/
|
||||||
|
setAuthToken(newToken, validityPeriod) {
|
||||||
|
Utils.delete_cookie(Constants.userConstants.PARTIAL_TOKEN);
|
||||||
|
Utils.setCookie(Constants.userConstants.PARTIAL_TOKEN, newToken, validityPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the user name of logged in user.
|
||||||
|
* @return String: User name
|
||||||
|
* */
|
||||||
|
getUserName() {
|
||||||
|
return this._userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide user data in JSON structure.
|
||||||
|
* @returns {JSON} : JSON representation of the user object
|
||||||
|
*/
|
||||||
|
toJson() {
|
||||||
|
return {
|
||||||
|
name: this._userName,
|
||||||
|
clientId: this._clientId,
|
||||||
|
clientSecret: this._clientSecret,
|
||||||
|
expires: this._expires
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User utility method to create an user from JSON object.
|
||||||
|
* @param {JSON} userJson : Need to provide user information in JSON structure to create an user object
|
||||||
|
* @returns {User} : An instance of User(this) class.
|
||||||
|
*/
|
||||||
|
static fromJson(userJson) {
|
||||||
|
const _user = new User(userJson.name);
|
||||||
|
_user._clientId = userJson.clientId;
|
||||||
|
_user._clientSecret = userJson.clientSecret;
|
||||||
|
_user._expires = userJson.expires;
|
||||||
|
|
||||||
|
console.log(_user);
|
||||||
|
return _user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
User._instance = null; // A private class variable to preserve the single instance of a swaggerClient
|
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for Publisher application
|
||||||
|
*/
|
||||||
|
class StoreUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Remove this method one the initial phase is done, This is used to continue the API class until the login page is create
|
||||||
|
* @returns {promise}
|
||||||
|
*/
|
||||||
|
// static autoLogin() {
|
||||||
|
// let auth = new AuthManager();
|
||||||
|
// return auth.authenticateUser('admin', 'admin');
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get JavaScript accessible cookies saved in browser, by giving the cooke name.
|
||||||
|
* @param {String} name : Name of the cookie which need to be retrived
|
||||||
|
* @returns {String|null} : If found a cookie with given name , return its value,Else null value is returned
|
||||||
|
*/
|
||||||
|
static getCookie(name) {
|
||||||
|
let pairs = document.cookie.split(";");
|
||||||
|
let cookie = null;
|
||||||
|
for (let pair of pairs) {
|
||||||
|
pair = pair.split("=");
|
||||||
|
let cookie_name = pair[0].trim();
|
||||||
|
let value = encodeURIComponent(pair[1]);
|
||||||
|
if (cookie_name === name) {
|
||||||
|
cookie = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a browser cookie given its name
|
||||||
|
* @param {String} name : Name of the cookie which need to be deleted
|
||||||
|
*/
|
||||||
|
static delete_cookie(name) {
|
||||||
|
document.cookie = name + '=; Path=' + "/" + '; Expires=Thu, 01 Jan 1970 00:00:01 GMT;';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a cookie with given name and value assigned to it. Cookies can be only set to the same origin,
|
||||||
|
* which the script is running
|
||||||
|
* @param {String} name : Name of the cookie which need to be set
|
||||||
|
* @param {String} value : Value of the cookie, expect it to be URLEncoded
|
||||||
|
* @param {number} validityPeriod : (Optional) Validity period of the cookie in seconds
|
||||||
|
* @param {String} path : Path which needs to set the given cookie
|
||||||
|
* @param {boolean} secured : secured parameter is set
|
||||||
|
*/
|
||||||
|
static setCookie(name, value, validityPeriod, path = "/", secured = true) {
|
||||||
|
let expires = "";
|
||||||
|
const securedDirective = secured ? "; Secure" : "";
|
||||||
|
if (validityPeriod) {
|
||||||
|
const date = new Date();
|
||||||
|
date.setTime(date.getTime() + validityPeriod * 1000);
|
||||||
|
expires = "; expires=" + date.toUTCString();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.cookie = name + "=" + value + expires + "; path=" + path + securedDirective + validityPeriod
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an object returns whether the object is empty or not
|
||||||
|
* @param {Object} object : Any JSON object
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
static isEmptyObject(object) {
|
||||||
|
return Object.keys(object).length === 0 && object.constructor === Object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default StoreUtils;
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper methods for app publisher.
|
||||||
|
* */
|
||||||
|
export default class Helper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate application object from form data passed.
|
||||||
|
* @param appData: Application data from the application creation form.
|
||||||
|
* @return {Object, Object}: The application object and the set of images related to the application.
|
||||||
|
* */
|
||||||
|
static buildApplication(appData) {
|
||||||
|
|
||||||
|
let application = {};
|
||||||
|
let images = {};
|
||||||
|
|
||||||
|
for (let step in appData) {
|
||||||
|
let tmpData = appData[step].data.step;
|
||||||
|
for (let prop in tmpData) {
|
||||||
|
if (prop === 'banner' || prop === 'screenshots' || prop === 'icon') {
|
||||||
|
images[prop] = tmpData[prop];
|
||||||
|
} else if(prop === 'tags') {
|
||||||
|
application[prop] = Helper.stringifyTags(tmpData[prop]);
|
||||||
|
} else {
|
||||||
|
application[prop] = tmpData[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {application, images};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a String array from tags array.
|
||||||
|
* */
|
||||||
|
static stringifyTags(tags) {
|
||||||
|
let tmpTags = [];
|
||||||
|
for (let tag in tags) {
|
||||||
|
console.log(tag);
|
||||||
|
tmpTags.push(tags[tag].value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmpTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import Axios from 'axios';
|
||||||
|
import AuthHandler from './authHandler';
|
||||||
|
import Constants from '../common/constants';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Api definitions for Platform management.
|
||||||
|
* */
|
||||||
|
export default class PlatformMgtApi{
|
||||||
|
/**
|
||||||
|
* Create a new Platform
|
||||||
|
* @param platformData: The platform data object.
|
||||||
|
* */
|
||||||
|
static createPlatform(platformData) {
|
||||||
|
const headers = AuthHandler.createAuthenticationHeaders("application/json");
|
||||||
|
Axios.post(Constants.platformManagerEndpoints.CREATE_PLATFORM, platformData, {headers: headers}).then(
|
||||||
|
function (response) {
|
||||||
|
console.log(response);
|
||||||
|
}
|
||||||
|
).catch(function (err) {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get available platforms
|
||||||
|
* */
|
||||||
|
static getPlatforms() {
|
||||||
|
const headers = AuthHandler.createAuthenticationHeaders("application/json");
|
||||||
|
return Axios.get(Constants.platformManagerEndpoints.GET_ENABLED_PLATFORMS, {headers: headers});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the user specified platform
|
||||||
|
* @param platformId: The identifier of the platform
|
||||||
|
* */
|
||||||
|
static getPlatform(platformId) {
|
||||||
|
const headers = AuthHandler.createAuthenticationHeaders("application/json");
|
||||||
|
return Axios.get(Constants.platformManagerEndpoints.GET_PLATFORM + platformId, {headers: headers});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete specified platform
|
||||||
|
* @param platformId: The id of the platform which is to be deleted.
|
||||||
|
* */
|
||||||
|
static deletePlatform(platformId) {
|
||||||
|
const headers = AuthHandler.createAuthenticationHeaders("application/json");
|
||||||
|
return Axios.delete(Constants.platformManagerEndpoints.GET_PLATFORM + platformId, {headers: headers});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
//TODO: Replace the server address with response from auth endpoint and remove hardcoded ids etc.
|
||||||
|
export default class Constants {
|
||||||
|
|
||||||
|
static scopes = 'perm:application:get perm:application:create perm:application:update perm:application-mgt:login' +
|
||||||
|
' perm:application:delete perm:platform:add perm:platform:remove perm:roles:view perm:devices:view';
|
||||||
|
|
||||||
|
static appManagerEndpoints = {
|
||||||
|
GET_ALL_APPS: 'https://localhost:8243/api/application-mgt/v1.0/applications/1.0.0/',
|
||||||
|
CREATE_APP: 'https://localhost:8243/api/application-mgt/v1.0/applications/1.0.0/',
|
||||||
|
UPLOAD_IMAGE_ARTIFACTS: 'https://localhost:8243/api/application-mgt/v1.0/applications/1.0.0/upload-image-artifacts/', //+appId
|
||||||
|
GET_IMAGE_ARTIFACTS: "https://localhost:8243/api/application-mgt/v1.0/applications/1.0.0/image-artifacts/"
|
||||||
|
};
|
||||||
|
|
||||||
|
static platformManagerEndpoints = {
|
||||||
|
CREATE_PLATFORM: 'https://localhost:8243/api/application-mgt/v1.0/platforms/1.0.0',
|
||||||
|
GET_ENABLED_PLATFORMS: 'https://localhost:8243/api/application-mgt/v1.0/platforms/1.0.0?status=ENABLED',
|
||||||
|
GET_PLATFORM: 'https://localhost:8243/api/application-mgt/v1.0/platforms/1.0.0/'
|
||||||
|
};
|
||||||
|
|
||||||
|
static userConstants = {
|
||||||
|
LOGIN_URL:"https://localhost:9443/auth/application-mgt/v1.0/auth/login",
|
||||||
|
LOGOUT_URL: "https://localhost:9443/auth/application-mgt/v1.0/auth/logout",
|
||||||
|
REFRESH_TOKEN_URL: "",
|
||||||
|
WSO2_USER: 'wso2_user',
|
||||||
|
PARTIAL_TOKEN: 'WSO2_IOT_TOKEN'
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {withRouter} from 'react-router-dom';
|
||||||
|
import AuthHandler from "../../api/authHandler";
|
||||||
|
import ApplicationCreate from '../Application/Create/ApplicationCreate';
|
||||||
|
import {Col, Container, Input, Row,} from 'reactstrap';
|
||||||
|
import FloatingButton from "../UIComponents/FloatingButton/FloatingButton";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base Layout:
|
||||||
|
* App bar
|
||||||
|
* Left Navigation
|
||||||
|
* Middle content.
|
||||||
|
* */
|
||||||
|
class BaseLayout extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.state = {
|
||||||
|
notifications: 0,
|
||||||
|
user: 'Admin',
|
||||||
|
openModal: false
|
||||||
|
};
|
||||||
|
this.logout = this.logout.bind(this);
|
||||||
|
this.closeModal = this.closeModal.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleApplicationClick() {
|
||||||
|
this.handleHistory('/assets/apps');
|
||||||
|
}
|
||||||
|
|
||||||
|
handleApplicationCreateClick(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
this.setState({openModal: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The method to update the history.
|
||||||
|
* to: The URL to route.
|
||||||
|
* */
|
||||||
|
handleHistory(to) {
|
||||||
|
this.props.history.push(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
logout(event, index, value) {
|
||||||
|
AuthHandler.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
closeModal() {
|
||||||
|
this.setState({openModal: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Container noGutters fluid id="container">
|
||||||
|
<div id="header-content">
|
||||||
|
<div id="header">
|
||||||
|
<span id="header-text">
|
||||||
|
WSO2 IoT App Publisher
|
||||||
|
</span>
|
||||||
|
<div id="header-btn-container">
|
||||||
|
<i className="fw fw-notification btn-header"></i>
|
||||||
|
<i className="fw fw-user btn-header"></i>
|
||||||
|
</div>
|
||||||
|
<div id="search-box">
|
||||||
|
<i className="fw fw-search search-icon">
|
||||||
|
</i>
|
||||||
|
<Input
|
||||||
|
id="search"
|
||||||
|
name="search"
|
||||||
|
placeholder={'Search for Applications'}
|
||||||
|
onChange={(event) => console.log(event.target.value)} //TODO: Remove this
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="add-btn-container">
|
||||||
|
<FloatingButton
|
||||||
|
className="add-btn small"
|
||||||
|
onClick={this.handleApplicationCreateClick.bind(this)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="application-content" style={this.state.style}>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
{this.props.children}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
<ApplicationCreate open={this.state.openModal} close={this.closeModal}/>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseLayout.propTypes = {
|
||||||
|
children: PropTypes.element
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withRouter(BaseLayout);
|
@ -0,0 +1,307 @@
|
|||||||
|
/*
|
||||||
|
* 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 {withRouter} from 'react-router-dom';
|
||||||
|
import {Button, Col, Row, Table} from 'reactstrap';
|
||||||
|
import Drawer from '../UIComponents/Drawer/Drawer';
|
||||||
|
import ApplicationView from './View/ApplicationView';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The App Create Component.
|
||||||
|
*
|
||||||
|
* Application creation is handled through a Wizard. (We use Material UI Stepper.)
|
||||||
|
*
|
||||||
|
* In each step, data will be set to the state separately.
|
||||||
|
* When the wizard is completed, data will be arranged and sent to the api.
|
||||||
|
* */
|
||||||
|
class ApplicationListing extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.searchApplications = this.searchApplications.bind(this);
|
||||||
|
this.onRowClick = this.onRowClick.bind(this);
|
||||||
|
this.setData = this.setData.bind(this);
|
||||||
|
this.sortData = this.sortData.bind(this);
|
||||||
|
this.compare = this.compare.bind(this);
|
||||||
|
this.handleButtonClick = this.handleButtonClick.bind(this);
|
||||||
|
this.state = {
|
||||||
|
searchedApplications: [],
|
||||||
|
applications: [],
|
||||||
|
asc: true,
|
||||||
|
open: false,
|
||||||
|
application: {},
|
||||||
|
drawer: {},
|
||||||
|
appListStyle: {},
|
||||||
|
//TODO: Remove this declaration.
|
||||||
|
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"
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
headers = [
|
||||||
|
{
|
||||||
|
data_id: "image",
|
||||||
|
data_type: "image",
|
||||||
|
sortable: false,
|
||||||
|
label: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "applicationName",
|
||||||
|
data_type: "string",
|
||||||
|
sortable: true,
|
||||||
|
label: "Application Name",
|
||||||
|
sort: this.sortData
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "platform",
|
||||||
|
data_type: "image_array",
|
||||||
|
sortable: false,
|
||||||
|
label: "Platform"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "category",
|
||||||
|
data_type: "string",
|
||||||
|
sortable: false,
|
||||||
|
label: "Category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "status",
|
||||||
|
data_type: "string",
|
||||||
|
sortable: false,
|
||||||
|
label: "Status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "edit",
|
||||||
|
data_type: "button",
|
||||||
|
sortable: false,
|
||||||
|
label: ""
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
applications = [
|
||||||
|
{
|
||||||
|
id: "3242342ffww3423",
|
||||||
|
applicationName: "Facebook",
|
||||||
|
platform: "android",
|
||||||
|
category: "Business",
|
||||||
|
status: "Published"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "http://dl1.cbsistatic.com/i/r/2016/08/08/0e67e43a-5a45-41ab-b81d-acfba8708044/resize/736x552/0c0ee669677b5060a0fa1bfb0c7873b4/android-logo-promo-470.png",
|
||||||
|
id: "324234233423423",
|
||||||
|
applicationName: "Twitter",
|
||||||
|
platform: "android",
|
||||||
|
category: "Business",
|
||||||
|
status: "Created"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "https://www.greenfoot.org/images/logos/macos.png",
|
||||||
|
id: "3242d3423423423",
|
||||||
|
applicationName: "Massenger",
|
||||||
|
platform: "android",
|
||||||
|
category: "Business",
|
||||||
|
status: "In Review"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
|
||||||
|
// let getApps = ApplicationMgtApi.getApplications();
|
||||||
|
// getApps.then(response => {
|
||||||
|
// let apps = this.setData(response.data.applications);
|
||||||
|
// console.log(apps); //TODO: Remove this.
|
||||||
|
// this.setState({searchedApplications: apps});
|
||||||
|
// // console.log(this.setState({data: response.data}), console.log(this.state));
|
||||||
|
// }).catch(err => {
|
||||||
|
// AuthHandler.unauthorizedErrorHandler(err);
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract application from application list and update the state.
|
||||||
|
* */
|
||||||
|
setData(applications) {
|
||||||
|
let apps = [];
|
||||||
|
for (let app in applications) {
|
||||||
|
let application = {};
|
||||||
|
application.id = applications[app].uuid;
|
||||||
|
application.applicationName = applications[app].name;
|
||||||
|
application.platform = applications[app].platform.name;
|
||||||
|
application.category = applications[app].category.id;
|
||||||
|
application.status = applications[app].currentLifecycle.lifecycleState.name;
|
||||||
|
apps.push(application);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({searchedApplications: apps});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the search action.
|
||||||
|
* When typing in the search bar, this method will be invoked.
|
||||||
|
* @param event: The event triggered from typing in the search box.
|
||||||
|
* @param searchText: The text that typed in the search box.
|
||||||
|
* */
|
||||||
|
searchApplications(event, searchText) {
|
||||||
|
let searchedData;
|
||||||
|
if (searchText) {
|
||||||
|
searchedData = this.state.applications.filter((dataItem) => {
|
||||||
|
return dataItem.applicationName.includes(searchText);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
searchedData = this.state.applications;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Remove the console log.
|
||||||
|
this.setState({searchedApplications: searchedData}, console.log("Searched data ", this.state.searchedApplications));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles sort data function and toggles the asc state.
|
||||||
|
* asc: true : sort in ascending order.
|
||||||
|
* */
|
||||||
|
sortData() {
|
||||||
|
console.log(this.state);
|
||||||
|
let isAsc = this.state.asc;
|
||||||
|
let sortedData = isAsc ? this.state.searchedApplications.sort(this.compare) : this.data.reverse();
|
||||||
|
this.setState({searchedApplications: sortedData, asc: !isAsc});
|
||||||
|
}
|
||||||
|
|
||||||
|
compare(a, b) {
|
||||||
|
if (a.applicationName < b.applicationName)
|
||||||
|
return -1;
|
||||||
|
if (a.applicationName > b.applicationName)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
onRowClick() {
|
||||||
|
let style = {
|
||||||
|
width: '500px',
|
||||||
|
marginLeft: '500px'
|
||||||
|
};
|
||||||
|
|
||||||
|
let appListStyle = {
|
||||||
|
marginRight: '500px',
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setState({drawer: style, appListStyle: appListStyle});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleButtonClick() {
|
||||||
|
console.log("Application Listing");
|
||||||
|
this.props.history.push("apps/edit/fdsfdsf343");
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(imageId) {
|
||||||
|
let tmp = this.state.image;
|
||||||
|
|
||||||
|
console.log(imageId);
|
||||||
|
|
||||||
|
let rem = tmp.filter((image) => {
|
||||||
|
return image.id !== imageId
|
||||||
|
|
||||||
|
});
|
||||||
|
this.setState({image: rem});
|
||||||
|
}
|
||||||
|
|
||||||
|
closeDrawer() {
|
||||||
|
let style = {
|
||||||
|
width: '0',
|
||||||
|
marginLeft: '0'
|
||||||
|
};
|
||||||
|
|
||||||
|
let appListStyle = {
|
||||||
|
marginRight: '0',
|
||||||
|
};
|
||||||
|
this.setState({drawer: style, appListStyle: appListStyle});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
|
||||||
|
<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>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
{/* TODO: Remove console.log and add sort method. */}
|
||||||
|
<th onClick={() => {
|
||||||
|
console.log("sort")
|
||||||
|
}}>Application Name
|
||||||
|
</th>
|
||||||
|
<th>Category</th>
|
||||||
|
<th>Platform</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{this.applications.map(
|
||||||
|
(application) => {
|
||||||
|
return (
|
||||||
|
<tr key={application.id} onClick={this.onRowClick}>
|
||||||
|
<td>
|
||||||
|
{/* TODO: Move this styles to css. */}
|
||||||
|
<img
|
||||||
|
src={application.icon}
|
||||||
|
height='50px'
|
||||||
|
width='50px'
|
||||||
|
style={{border: 'solid 1px black', borderRadius: "100%"}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>{application.applicationName}</td>
|
||||||
|
<td>{application.category}</td>
|
||||||
|
<td>{application.platform}</td>
|
||||||
|
<td>{application.status}</td>
|
||||||
|
<td>
|
||||||
|
<Button onClick={this.handleButtonClick}>
|
||||||
|
<i className="fw fw-edit"></i>
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</Table>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Drawer onClose={this.closeDrawer.bind(this)} style={this.state.drawer}>
|
||||||
|
<ApplicationView/>
|
||||||
|
</Drawer>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationListing.propTypes = {};
|
||||||
|
|
||||||
|
export default withRouter(ApplicationListing);
|
@ -0,0 +1,243 @@
|
|||||||
|
/*
|
||||||
|
* 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 {withRouter} from 'react-router-dom';
|
||||||
|
import AuthHandler from "../../../api/authHandler";
|
||||||
|
import {Step1, Step2, Step3, Step4} from './CreateSteps/index';
|
||||||
|
import ApplicationMgtApi from '../../../api/applicationMgtApi';
|
||||||
|
import {Button, Col, Modal, ModalBody, ModalFooter, ModalHeader, Row} from 'reactstrap';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The App Create Component.
|
||||||
|
*
|
||||||
|
* Application creation is handled through a Wizard. (We use Material UI Stepper.)
|
||||||
|
*
|
||||||
|
* In each step, data will be set to the state separately.
|
||||||
|
* When the wizard is completed, data will be arranged and sent to the api.
|
||||||
|
* */
|
||||||
|
class ApplicationCreate extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.scriptId = "application-create";
|
||||||
|
this.setStepData = this.setStepData.bind(this);
|
||||||
|
this.removeStepData = this.removeStepData.bind(this);
|
||||||
|
this.onSubmit = this.onSubmit.bind(this);
|
||||||
|
this.handleCancel = this.handleCancel.bind(this);
|
||||||
|
this.handleYes = this.handleYes.bind(this);
|
||||||
|
this.handleNo = this.handleNo.bind(this);
|
||||||
|
this.onPrevClick = this.onPrevClick.bind(this);
|
||||||
|
this.onNextClick = this.onNextClick.bind(this);
|
||||||
|
this.onClose = this.onClose.bind(this);
|
||||||
|
this.state = {
|
||||||
|
finished: false,
|
||||||
|
stepIndex: 0,
|
||||||
|
stepData: [],
|
||||||
|
isDialogOpen: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(props, nextprops) {
|
||||||
|
this.setState({open: props.open})
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.setState({open: this.props.open});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onClose() {
|
||||||
|
this.setState({stepIndex: 0}, this.props.close());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles next button click event.
|
||||||
|
* */
|
||||||
|
onNextClick() {
|
||||||
|
console.log("Handle Next"); //TODO: Remove this
|
||||||
|
const {stepIndex} = this.state;
|
||||||
|
this.setState({
|
||||||
|
stepIndex: stepIndex + 1,
|
||||||
|
finished: stepIndex >= 2,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles form submit.
|
||||||
|
* */
|
||||||
|
onSubmit() {
|
||||||
|
let stepData = this.state.stepData;
|
||||||
|
let applicationCreationPromise = ApplicationMgtApi.createApplication(stepData);
|
||||||
|
applicationCreationPromise.then(response => {
|
||||||
|
this.handleYes();
|
||||||
|
}
|
||||||
|
).catch(
|
||||||
|
function (err) {
|
||||||
|
AuthHandler.unauthorizedErrorHandler(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles cancel button click event.
|
||||||
|
* This will show a confirmation dialog to cancel the application creation process.
|
||||||
|
* */
|
||||||
|
handleCancel() {
|
||||||
|
this.setState({isDialogOpen: true});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handled [ < Prev ] button click.
|
||||||
|
* This clears the data in the current step and returns to the previous step.
|
||||||
|
* */
|
||||||
|
onPrevClick() {
|
||||||
|
const {stepIndex} = this.state;
|
||||||
|
if (stepIndex > 0) {
|
||||||
|
this.removeStepData();
|
||||||
|
this.setState({stepIndex: stepIndex - 1});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves form data in each step in to the state.
|
||||||
|
* @param step: The step number of the step data.
|
||||||
|
* @param data: The form data of the step.
|
||||||
|
* */
|
||||||
|
setStepData(step, data) {
|
||||||
|
console.log(step, data, this.state.stepData); //TODO: Remove this
|
||||||
|
let tmpStepData = this.state.stepData;
|
||||||
|
tmpStepData.push({step: step, data: data});
|
||||||
|
|
||||||
|
this.setState({stepData: tmpStepData}, this.onNextClick())
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the last data point
|
||||||
|
* */
|
||||||
|
removeStepData() {
|
||||||
|
let tempData = this.state.stepData;
|
||||||
|
tempData.pop();
|
||||||
|
this.setState({stepData: tempData});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the Yes button in app creation cancellation dialog.
|
||||||
|
* Clears all the form data and reset the wizard.
|
||||||
|
* */
|
||||||
|
handleYes() {
|
||||||
|
this.setState({finished: false, stepIndex: 0, stepData: [], isDialogOpen: false});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles No button in app creation cancellation dialog.
|
||||||
|
* Returns to the same step.
|
||||||
|
* */
|
||||||
|
handleNo() {
|
||||||
|
this.setState({isDialogOpen: false});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines all the Steps in the stepper. (Wizard)
|
||||||
|
*
|
||||||
|
* Extension Point: If any extra steps needed, follow the instructions below.
|
||||||
|
* 1. Create the required form ./Forms directory.
|
||||||
|
* 2. Add defined case statements.
|
||||||
|
* 3. Define the Step in render function.
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
getStepContent(stepIndex) {
|
||||||
|
switch (stepIndex) {
|
||||||
|
case 0:
|
||||||
|
return (
|
||||||
|
<Step1
|
||||||
|
handleNext={this.onNextClick}
|
||||||
|
setData={this.setStepData}
|
||||||
|
removeData={this.removeStepData}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case 1:
|
||||||
|
return (
|
||||||
|
<Step2
|
||||||
|
handleNext={this.onNextClick}
|
||||||
|
handlePrev={this.onPrevClick}
|
||||||
|
setData={this.setStepData}
|
||||||
|
removeData={this.removeStepData}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case 2:
|
||||||
|
return (
|
||||||
|
<Step3
|
||||||
|
handleFinish={this.onNextClick}
|
||||||
|
handlePrev={this.onPrevClick}
|
||||||
|
setData={this.setStepData}
|
||||||
|
removeData={this.removeStepData}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
case 3: {
|
||||||
|
return (
|
||||||
|
<Step4
|
||||||
|
handleNext={this.onNextClick}
|
||||||
|
setData={this.setStepData}
|
||||||
|
removeData={this.removeStepData}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return <div/>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {finished, stepIndex} = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="create-application-modal">
|
||||||
|
<Modal isOpen={this.state.open} toggle={this.toggle} id="app-create-modal"
|
||||||
|
backdrop={'static'}>
|
||||||
|
<ModalHeader toggle={this.toggle}>Create Application</ModalHeader>
|
||||||
|
<ModalBody id="modal-body-content">
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<div className="stepper-header">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
{this.getStepContent(stepIndex)}
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
{stepIndex === 0 ? <div/> :
|
||||||
|
<Button color="primary" onClick={this.onPrevClick}>Back</Button>}
|
||||||
|
<Button color="secondary" onClick={this.onClose}>Cancel</Button>
|
||||||
|
{finished ?
|
||||||
|
<Button color="primary" onClick={this.onSubmit}>Finish</Button> :
|
||||||
|
<Button color="primary" onClick={this.onNextClick}>Continue</Button>}
|
||||||
|
</ModalFooter>
|
||||||
|
</Modal>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplicationCreate.propTypes = {};
|
||||||
|
|
||||||
|
export default withRouter(ApplicationCreate);
|
@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {Badge, FormGroup, Input, Label} from 'reactstrap';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Second step of application create wizard.
|
||||||
|
* This contains following components.
|
||||||
|
* * App Title
|
||||||
|
* * Short Description
|
||||||
|
* * Application Description
|
||||||
|
* * Application Visibility
|
||||||
|
* * Application Tags : {Used Material UI Chip component}
|
||||||
|
* * Application Category.
|
||||||
|
* * Platform Specific properties.
|
||||||
|
*
|
||||||
|
* Parent Component: Create
|
||||||
|
* Props:
|
||||||
|
* * onNextClick : {type: function, Invokes onNextClick function in Parent.}
|
||||||
|
* * onPrevClick : {type: function, Invokes onPrevClick function in Parent}
|
||||||
|
* * setData : {type: function, Invokes setStepData function in Parent}
|
||||||
|
* * removeData : {type: Invokes removeStepData function in Parent}
|
||||||
|
* */
|
||||||
|
class Step1 extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.state = {
|
||||||
|
tags: [],
|
||||||
|
icon: [],
|
||||||
|
title: "",
|
||||||
|
errors: {},
|
||||||
|
banner: [],
|
||||||
|
defValue: "",
|
||||||
|
category: 0,
|
||||||
|
visibility: 0,
|
||||||
|
description: "",
|
||||||
|
screenshots: [],
|
||||||
|
identifier: "",
|
||||||
|
shortDescription: ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Chip delete function.
|
||||||
|
* Removes the tag from state.tags
|
||||||
|
* */
|
||||||
|
handleRequestDelete(event) {
|
||||||
|
this.chipData = this.state.tags;
|
||||||
|
console.log(event.target);
|
||||||
|
const chipToDelete = this.chipData.map((chip) => chip.value).indexOf(event.target.value);
|
||||||
|
this.chipData.splice(chipToDelete, 1);
|
||||||
|
this.setState({tags: this.chipData});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an object with the current step data and persist in the parent.
|
||||||
|
* */
|
||||||
|
setStepData() {
|
||||||
|
let stepData = {};
|
||||||
|
this.props.setData("step1", {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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="createStep2Content">
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<FormGroup>
|
||||||
|
<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
|
||||||
|
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"
|
||||||
|
onChange={this.handleTagChange.bind(this)}
|
||||||
|
onKeyPress={this.addTags.bind(this)}
|
||||||
|
/>
|
||||||
|
<div id="batch-content">
|
||||||
|
{this.state.tags.map(tag => {
|
||||||
|
return (
|
||||||
|
<Badge
|
||||||
|
style={{margin: '0 2px 0 2px'}}
|
||||||
|
value={tag.value}
|
||||||
|
onClick={this.handleRequestDelete.bind(this)}
|
||||||
|
>
|
||||||
|
{tag.value}
|
||||||
|
</Badge>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</FormGroup>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Step1.prototypes = {
|
||||||
|
handleNext: PropTypes.func,
|
||||||
|
handlePrev: PropTypes.func,
|
||||||
|
setData: PropTypes.func,
|
||||||
|
removeData: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Step1;
|
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import AuthHandler from "../../../../api/authHandler";
|
||||||
|
import PlatformMgtApi from "../../../../api/platformMgtApi";
|
||||||
|
import {FormGroup, Input, Label} from 'reactstrap';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first step of the application creation wizard.
|
||||||
|
* This contains following components:
|
||||||
|
* * Application Title
|
||||||
|
* * Store Type
|
||||||
|
* * Application Platform
|
||||||
|
*
|
||||||
|
* Parent Component: Create
|
||||||
|
* Props:
|
||||||
|
* 1. onNextClick: {type: function, Invokes onNextClick function of parent component}
|
||||||
|
* 2. setData : {type: function, Sets current form data to the state of the parent component}
|
||||||
|
* 3. removeData: {type: function, Invokes the removeStepData function click of parent}
|
||||||
|
* */
|
||||||
|
class Step2 extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.setPlatforms = this.setPlatforms.bind(this);
|
||||||
|
this.setStepData = this.setStepData.bind(this);
|
||||||
|
this.platforms = [];
|
||||||
|
this.state = {
|
||||||
|
finished: false,
|
||||||
|
stepIndex: 0,
|
||||||
|
store: 1,
|
||||||
|
platformSelectedIndex: 0,
|
||||||
|
platform: "",
|
||||||
|
platforms: [],
|
||||||
|
stepData: [],
|
||||||
|
title: "",
|
||||||
|
titleError: ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
* @param platforms: The array returned as the response.
|
||||||
|
* */
|
||||||
|
setPlatforms(platforms) {
|
||||||
|
let tmpPlatforms = [];
|
||||||
|
for (let index in platforms) {
|
||||||
|
let platform = {};
|
||||||
|
platform = platforms[index];
|
||||||
|
tmpPlatforms.push(platform);
|
||||||
|
}
|
||||||
|
this.setState({platforms: tmpPlatforms, platformSelectedIndex: 0, platform: tmpPlatforms[0].name})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persist the current form data to the state.
|
||||||
|
* */
|
||||||
|
setStepData() {
|
||||||
|
let step = {
|
||||||
|
store: this.state.store,
|
||||||
|
platform: this.state.platforms[this.state.platformSelectedIndex]
|
||||||
|
};
|
||||||
|
this.props.setData("step2", {step: step});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers when changing the Platform selection.
|
||||||
|
* */
|
||||||
|
onChangePlatform(event) {
|
||||||
|
console.log(event.target.value, this.state.platforms);
|
||||||
|
let id = event.target.value;
|
||||||
|
let selectedPlatform = this.state.platforms.filter((platform) => {
|
||||||
|
return platform.identifier === id;
|
||||||
|
});
|
||||||
|
this.setState({platform: selectedPlatform});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers when changing the Store selection.
|
||||||
|
* */
|
||||||
|
onChangeStore(event) {
|
||||||
|
this.setState({store: event.target.value});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<FormGroup>
|
||||||
|
<Label for="store">Store Type</Label>
|
||||||
|
<Input
|
||||||
|
type="select"
|
||||||
|
name="store"
|
||||||
|
className="input-custom"
|
||||||
|
onChange={this.onChangeStore.bind(this)}
|
||||||
|
>
|
||||||
|
<option>Enterprise</option>
|
||||||
|
<option>Public</option>
|
||||||
|
</Input>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup>
|
||||||
|
<Label for="store">Platform</Label>
|
||||||
|
<Input
|
||||||
|
type="select"
|
||||||
|
name="store"
|
||||||
|
onChange={this.onChangePlatform.bind(this)}
|
||||||
|
>
|
||||||
|
{this.state.platforms.length > 0 ? this.state.platforms.map(platform => {
|
||||||
|
return (
|
||||||
|
<option value={platform.identifier}>
|
||||||
|
{platform.name}
|
||||||
|
</option>
|
||||||
|
)
|
||||||
|
}) : <option>No Platforms</option>}
|
||||||
|
</Input>
|
||||||
|
</FormGroup>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Step2.propTypes = {
|
||||||
|
handleNext: PropTypes.func,
|
||||||
|
setData: PropTypes.func,
|
||||||
|
removeData: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Step2;
|
@ -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 PropTypes from 'prop-types';
|
||||||
|
import Chip from 'material-ui/Chip';
|
||||||
|
import Dropzone from 'react-dropzone';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import MenuItem from 'material-ui/MenuItem';
|
||||||
|
import SelectField from 'material-ui/SelectField';
|
||||||
|
import {FormGroup, Label} from 'reactstrap';
|
||||||
|
import AppImage from "../../../UIComponents/AppImage/AppImage";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Third step of application create wizard.
|
||||||
|
* This contains following components.
|
||||||
|
* * Screenshots
|
||||||
|
* * Banner
|
||||||
|
* * Icon
|
||||||
|
*
|
||||||
|
* Parent Component: Create
|
||||||
|
* Props:
|
||||||
|
* * onNextClick : {type: function, Invokes onNextClick function in Parent.}
|
||||||
|
* * onPrevClick : {type: function, Invokes onPrevClick function in Parent}
|
||||||
|
* * setData : {type: function, Invokes setStepData function in Parent}
|
||||||
|
* * removeData : {type: Invokes removeStepData function in Parent}
|
||||||
|
* */
|
||||||
|
class Step3 extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.state = {
|
||||||
|
tags: [],
|
||||||
|
icon: [],
|
||||||
|
title: "",
|
||||||
|
errors: {},
|
||||||
|
banner: [],
|
||||||
|
defValue: "",
|
||||||
|
category: 0,
|
||||||
|
visibility: 0,
|
||||||
|
description: "",
|
||||||
|
screenshots: [],
|
||||||
|
identifier: "",
|
||||||
|
shortDescription: ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Chip delete function.
|
||||||
|
* Removes the tag from state.tags
|
||||||
|
* */
|
||||||
|
handleRequestDelete(event) {
|
||||||
|
this.chipData = this.state.tags;
|
||||||
|
console.log(event.target); //TODO: Remove Console log.
|
||||||
|
const chipToDelete = this.chipData.map((chip) => chip.value).indexOf(event.target.value);
|
||||||
|
this.chipData.splice(chipToDelete, 1);
|
||||||
|
this.setState({tags: this.chipData});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an object with the current step data and persist in the parent.
|
||||||
|
* */
|
||||||
|
setStepData() {
|
||||||
|
let stepData = {
|
||||||
|
icon: this.state.icon,
|
||||||
|
banner: this.state.banner,
|
||||||
|
screenshots: this.state.screenshots
|
||||||
|
};
|
||||||
|
|
||||||
|
this.props.setData("step2", {step: stepData});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removed user uploaded banner.
|
||||||
|
* */
|
||||||
|
removeBanner(event, d) {
|
||||||
|
console.log(event, d); //TODO: Remove this
|
||||||
|
this.setState({banner: []});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes uploaded icon.
|
||||||
|
* */
|
||||||
|
removeIcon(event) {
|
||||||
|
this.setState({icon: []});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes selected screenshot.
|
||||||
|
* */
|
||||||
|
removeScreenshot(event) {
|
||||||
|
console.log(event.target) //TODO: Remove this.
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO: Remove inline css.
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="createStep2Content">
|
||||||
|
<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) => (
|
||||||
|
<div id="app-image-screenshot">
|
||||||
|
<AppImage image={tile[0].preview}/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{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); //TODO: Remove this
|
||||||
|
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) => (
|
||||||
|
<div id="app-image-icon">
|
||||||
|
<AppImage image={tile.preview}/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{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) => (
|
||||||
|
<div id="app-image-banner">
|
||||||
|
<AppImage image={tile.preview}/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Step3.prototypes = {
|
||||||
|
handleNext: PropTypes.func,
|
||||||
|
handlePrev: PropTypes.func,
|
||||||
|
setData: PropTypes.func,
|
||||||
|
removeData: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Step3;
|
@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {Collapse, FormGroup, Input, Label, FormText} from 'reactstrap';
|
||||||
|
import Switch from '../../../UIComponents/Switch/Switch'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Third step of application create wizard. {Application Release Step}
|
||||||
|
* This step is not compulsory.
|
||||||
|
*
|
||||||
|
* When click finish, user will prompt to confirm the application creation.
|
||||||
|
* User can go ahead and create the app or cancel.
|
||||||
|
*
|
||||||
|
* This contains following components:
|
||||||
|
* * Toggle to select application release. Un-hides the Application Release form.
|
||||||
|
*
|
||||||
|
* Application Release Form.
|
||||||
|
* * Release Channel
|
||||||
|
* * Application Version
|
||||||
|
* * Upload component for application.
|
||||||
|
*
|
||||||
|
* Parent Component: Create
|
||||||
|
* Props:
|
||||||
|
* * handleFinish : {type: function, Invokes onNextClick function in Parent.}
|
||||||
|
* * onPrevClick : {type: function, Invokes onPrevClick function in Parent}
|
||||||
|
* * setData : {type: function, Invokes setStepData function in Parent}
|
||||||
|
* * removeData : {type: Invokes removeStepData function in Parent}
|
||||||
|
* */
|
||||||
|
class Step4 extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.handleToggle = this.handleToggle.bind(this);
|
||||||
|
this.handlePrev = this.handlePrev.bind(this);
|
||||||
|
this.handleToggle = this.handleToggle.bind(this);
|
||||||
|
this.handleFinish = this.handleFinish.bind(this);
|
||||||
|
this.state = {
|
||||||
|
showForm: false,
|
||||||
|
releaseChannel: 1,
|
||||||
|
errors: {}
|
||||||
|
};
|
||||||
|
this.scriptId = "application-create-step3";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles finish button click.
|
||||||
|
* This invokes onNextClick function in parent component.
|
||||||
|
* */
|
||||||
|
handleFinish() {
|
||||||
|
this.props.handleFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes Prev button click.
|
||||||
|
* */
|
||||||
|
handlePrev() {
|
||||||
|
this.props.handlePrev();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles release application selection.
|
||||||
|
* */
|
||||||
|
handleToggle() {
|
||||||
|
let hide = this.state.showForm;
|
||||||
|
this.setState({showForm: !hide});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="applicationCreateStepMiddle">
|
||||||
|
<div>
|
||||||
|
<FormGroup>
|
||||||
|
<div id="app-release-switch-content">
|
||||||
|
<div id="app-release-switch-label">
|
||||||
|
<Label for="app-release-switch">
|
||||||
|
<strong>
|
||||||
|
Add Release to Application
|
||||||
|
</strong>
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div id="app-release-switch-switch">
|
||||||
|
<Switch
|
||||||
|
id="app-release-switch"
|
||||||
|
onChange={this.handleToggle.bind(this)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FormGroup>
|
||||||
|
<br/>
|
||||||
|
<div>
|
||||||
|
<FormText color="muted">
|
||||||
|
<i>Info: </i>
|
||||||
|
Enabling this will create a release for the current Application.
|
||||||
|
To upload the Application, please visit to the Release management section of
|
||||||
|
Application Edit View.
|
||||||
|
</FormText>
|
||||||
|
</div>
|
||||||
|
{/*If toggle is true, the release form will be shown.*/}
|
||||||
|
<Collapse isOpen={this.state.showForm}>
|
||||||
|
<FormGroup>
|
||||||
|
<Label for="release-channel">Release Channel</Label>
|
||||||
|
<Input
|
||||||
|
type="select"
|
||||||
|
id="release-channel"
|
||||||
|
style={{
|
||||||
|
width: '200px',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: '0',
|
||||||
|
borderBottom: 'solid 1px #BDBDBD'
|
||||||
|
}}>
|
||||||
|
<option>GA</option>
|
||||||
|
<option>Alpha</option>
|
||||||
|
<option>Beta</option>
|
||||||
|
</Input>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup>
|
||||||
|
<Label for="version">Version*</Label>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
id="version input-custom"
|
||||||
|
placeholder="v1.0"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</Collapse>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Step4.propTypes = {
|
||||||
|
handleFinish: PropTypes.func,
|
||||||
|
handlePrev: PropTypes.func,
|
||||||
|
setData: PropTypes.func,
|
||||||
|
removeData: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Step4;
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* 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 Step1 from './Step1';
|
||||||
|
import Step2 from './Step2';
|
||||||
|
import Step3 from './Step3';
|
||||||
|
import Step4 from './Step4';
|
||||||
|
|
||||||
|
export {Step1, Step2, Step3, Step4};
|
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* 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 {Col, Row} from "reactstrap";
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import GeneralInfo from "../GenenralInfo/GeneralInfo";
|
||||||
|
import ReleaseManager from '../../Release/ReleaseMgtBase/ReleaseManager';
|
||||||
|
|
||||||
|
class ApplicationEdit extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.getTabContent = this.getTabContent.bind(this);
|
||||||
|
this.state = {
|
||||||
|
general: "active",
|
||||||
|
release: "",
|
||||||
|
pkgmgt: "",
|
||||||
|
activeTab: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTabClick(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
const key = event.target.value;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case "1": {
|
||||||
|
this.setState({activeTab: 1, general: "active", release: "", pkgmgt: ""});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "2": {
|
||||||
|
this.setState({activeTab: 2, general: "", release: "active", pkgmgt: ""});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "3": {
|
||||||
|
this.setState({activeTab: 3, general: "", release: "", pkgmgt: "active"});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return "No Content";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getTabContent(tab) {
|
||||||
|
switch (tab) {
|
||||||
|
case 1: {
|
||||||
|
return <GeneralInfo/>
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
return <ReleaseManager/>
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
return ("Step3")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnBackClick() {
|
||||||
|
window.location.href = "/publisher/assets/apps"
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div id="application-edit-base">
|
||||||
|
<Row id="application-edit-header">
|
||||||
|
<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 id="application-edit-main-container">
|
||||||
|
<Col xs="3">
|
||||||
|
<div className="tab">
|
||||||
|
<button className={this.state.general} value={1} onClick={this.handleTabClick.bind(this)}>
|
||||||
|
General
|
||||||
|
</button>
|
||||||
|
<button className={this.state.release} value={2} onClick={this.handleTabClick.bind(this)}>
|
||||||
|
App
|
||||||
|
Releases
|
||||||
|
</button>
|
||||||
|
<button className={this.state.pkgmgt} value={3} onClick={this.handleTabClick.bind(this)}>
|
||||||
|
Package Manager
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col xs="9">
|
||||||
|
<div id="app-edit-content">
|
||||||
|
<Row>
|
||||||
|
<Col xs="12">
|
||||||
|
<div id="application-edit-outer-content">
|
||||||
|
{/* Application edit content */}
|
||||||
|
<div id="application-edit-content">
|
||||||
|
{this.getTabContent(this.state.activeTab)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ApplicationEdit;
|
@ -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;
|
||||||
|
|
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
|
||||||
|
class PackageManager extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return(
|
||||||
|
<div id="package-mgt-content">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PackageManager;
|
@ -0,0 +1,172 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {Button, FormGroup, FormText, Input, Label, Row} from "reactstrap";
|
||||||
|
import UploadPackage from "./UploadPackage";
|
||||||
|
|
||||||
|
class CreateRelease extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.onTestMethodChange = this.onTestMethodChange.bind(this);
|
||||||
|
this.showUploadArtifacts = this.showUploadArtifacts.bind(this);
|
||||||
|
this.onBackClick = this.onBackClick.bind(this);
|
||||||
|
this.onBackToRelease = this.onBackToRelease.bind(this);
|
||||||
|
this.state = {
|
||||||
|
open: true,
|
||||||
|
hiddenMain: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onTestMethodChange(event) {
|
||||||
|
let type = event.target.value;
|
||||||
|
if (type !== 'open') {
|
||||||
|
this.setState({open: false})
|
||||||
|
} else {
|
||||||
|
this.setState({open: true})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showUploadArtifacts() {
|
||||||
|
this.setState({hiddenMain: true})
|
||||||
|
}
|
||||||
|
|
||||||
|
onBackClick() {
|
||||||
|
this.props.handleBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
onBackToRelease() {
|
||||||
|
this.setState({hiddenMain: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {channel} = this.props;
|
||||||
|
console.log(channel);
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
{this.state.hiddenMain ?
|
||||||
|
<div>
|
||||||
|
<UploadPackage
|
||||||
|
backToRelease={this.onBackToRelease}
|
||||||
|
selectedChannel={channel}
|
||||||
|
/>
|
||||||
|
</div> :
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Row>
|
||||||
|
<div className="release-header">
|
||||||
|
<a onClick={this.onBackClick}>{"<-"}</a>
|
||||||
|
<span id="create-release-header">
|
||||||
|
<strong>{channel} Release</strong>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<div className="release-create">
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
<strong>Create Release</strong>
|
||||||
|
</span>
|
||||||
|
<p>
|
||||||
|
{channel === 'Production' ? "" :
|
||||||
|
"You could create " + channel + " release for your application and let " +
|
||||||
|
"the test users to test the application for it's stability."}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button id="create-release-btn" onClick={this.showUploadArtifacts}>Create a {channel} Release</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
{channel !== 'Production' ?
|
||||||
|
<Row>
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
<strong>Manage Test Method</strong>
|
||||||
|
</span>
|
||||||
|
<p>
|
||||||
|
This section allows you to change the test method and the users who would be
|
||||||
|
able to test your application.
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<form>
|
||||||
|
<FormGroup>
|
||||||
|
<Label for="test-method">Test Method*</Label>
|
||||||
|
<Input
|
||||||
|
required
|
||||||
|
type="select"
|
||||||
|
name="testMethod"
|
||||||
|
id="test-method"
|
||||||
|
onChange={this.onTestMethodChange}
|
||||||
|
>
|
||||||
|
<option value="open">Open {channel}</option>
|
||||||
|
<option value="closed">Closed {channel}</option>
|
||||||
|
</Input>
|
||||||
|
</FormGroup>
|
||||||
|
{!this.state.open ? (
|
||||||
|
<FormGroup>
|
||||||
|
<Label for="user-list">Users List*</Label>
|
||||||
|
<Input
|
||||||
|
required
|
||||||
|
name="userList"
|
||||||
|
id="user-list"
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
<FormText color="muted">
|
||||||
|
Provide a comma separated list of email
|
||||||
|
addresses.
|
||||||
|
</FormText>
|
||||||
|
</FormGroup>
|
||||||
|
) : <div/>}
|
||||||
|
<FormGroup>
|
||||||
|
<Label for="app-title">Feedback Method*</Label>
|
||||||
|
<Input
|
||||||
|
required
|
||||||
|
name="appName"
|
||||||
|
id="app-title"
|
||||||
|
/>
|
||||||
|
<FormText color="muted">
|
||||||
|
Provide an Email address or a URL for your users to provide
|
||||||
|
feedback on the application.
|
||||||
|
</FormText>
|
||||||
|
</FormGroup>
|
||||||
|
<div>
|
||||||
|
<Button className="form-btn">Save</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Row> :
|
||||||
|
<div/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateRelease.propTypes = {
|
||||||
|
channel: PropTypes.string,
|
||||||
|
handleBack: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CreateRelease;
|
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {Button, Col, FormGroup, Input, Label, Row} from "reactstrap";
|
||||||
|
|
||||||
|
class UploadPackage extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.handleBack = this.handleBack.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBack() {
|
||||||
|
this.props.onBackToRelease();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {selectedChannel} = this.props;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Row>
|
||||||
|
<div className="release-header">
|
||||||
|
<a onClick={this.handleBack}>{"<-"}</a>
|
||||||
|
<span id="create-release-header">
|
||||||
|
<strong>New Release for {selectedChannel}</strong>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<div className="release-header">
|
||||||
|
<span id="create-release-header">
|
||||||
|
<strong>Upload Package File</strong>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col xs="3">
|
||||||
|
<Button>Upload</Button>
|
||||||
|
</Col>
|
||||||
|
<Col xs="3">
|
||||||
|
<Button>Select from package library</Button>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<div className="release-detail-content">
|
||||||
|
<form>
|
||||||
|
<FormGroup>
|
||||||
|
<Label>Release Name *</Label>
|
||||||
|
<Input
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup>
|
||||||
|
<Label>Release Notes *</Label>
|
||||||
|
<Input
|
||||||
|
required
|
||||||
|
type="textarea"
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
<div className="form-btn">
|
||||||
|
<Button>Send for Review</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UploadPackage.protoTypes = {
|
||||||
|
backToRelease: PropTypes.func,
|
||||||
|
channel: PropTypes.string
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UploadPackage;
|
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {Button, Col, Row} from "reactstrap";
|
||||||
|
import CreateRelease from "../Create/CreateRelease";
|
||||||
|
|
||||||
|
class ReleaseManager extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.getNoReleaseContent = this.getNoReleaseContent.bind(this);
|
||||||
|
this.onCreateRelease = this.onCreateRelease.bind(this);
|
||||||
|
this.onBackClick = this.onBackClick.bind(this);
|
||||||
|
this.state = {
|
||||||
|
createRelease: false,
|
||||||
|
onGoing: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCreateRelease(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.setState({createRelease: true, onGoing: event.target.value})
|
||||||
|
}
|
||||||
|
|
||||||
|
onBackClick() {
|
||||||
|
this.setState({createRelease: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds a generic message saying there are no current release in the specified release channel.
|
||||||
|
* */
|
||||||
|
getNoReleaseContent(release) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Row>
|
||||||
|
<Col sm="12" md={{size: 8, offset: 4}}>
|
||||||
|
<p>You have no on-going {release} Releases!</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col sm="12" md={{size: 8, offset: 5}}>
|
||||||
|
<Button
|
||||||
|
className="button-add"
|
||||||
|
id={release.toLowerCase()}
|
||||||
|
value={release}
|
||||||
|
onClick={this.onCreateRelease}
|
||||||
|
>
|
||||||
|
Create a Release
|
||||||
|
</Button>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{this.state.createRelease ?
|
||||||
|
<CreateRelease
|
||||||
|
channel={this.state.onGoing}
|
||||||
|
handleBack={this.onBackClick}
|
||||||
|
/> :
|
||||||
|
<div id="release-mgt-content">
|
||||||
|
<Row>
|
||||||
|
<Col sm="12">
|
||||||
|
<div className="release" id="production">
|
||||||
|
<span>Production Releases</span>
|
||||||
|
<div className="release-content">
|
||||||
|
<div className="release-inner">
|
||||||
|
{this.getNoReleaseContent("Production")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col sm="12">
|
||||||
|
<div className="release" id="beta">
|
||||||
|
<span>Beta Releases</span>
|
||||||
|
<div className="release-content">
|
||||||
|
<div className="release-inner">
|
||||||
|
{this.getNoReleaseContent("Beta")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col sm="12">
|
||||||
|
<div className="release" id="alpha">
|
||||||
|
<span>Alpha Releases</span>
|
||||||
|
<div className="release-content">
|
||||||
|
<div className="release-inner">
|
||||||
|
{this.getNoReleaseContent("Alpha")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReleaseManager;
|
@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* 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 {withRouter} from 'react-router-dom';
|
||||||
|
import {Col, Row} from "reactstrap";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application view component.
|
||||||
|
* Shows the details of the application.
|
||||||
|
* */
|
||||||
|
class ApplicationView extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.state = {
|
||||||
|
application: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillReceiveProps(props, nextProps) {
|
||||||
|
this.setState({application: props.application});
|
||||||
|
console.log(props.application, nextProps)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
//TODO: Download image artifacts.
|
||||||
|
}
|
||||||
|
|
||||||
|
handleEdit() {
|
||||||
|
this.props.history.push("/assets/apps/edit/" + this.state.application.uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const platform = this.state.application;
|
||||||
|
console.log(platform);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div id="application-view-content">
|
||||||
|
<div id="application-view-row">
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<div id="app-icon">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<Row>
|
||||||
|
<span><strong>Facebook</strong></span>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<span className="app-updated-date">Last updated on 2017-09-23</span>
|
||||||
|
</Row>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
<div id="application-view-row">
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<span className="app-install-count">2k Installs</span>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div id="application-view-row">
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<span><strong>Description: </strong></span>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<p>sdfjlkdsjfsjdfjsdf sfjdslkjfdsflkjdsfslkdjfl j</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<span><strong>Tags: </strong></span>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<p>[list of tags...]</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<span><strong>Release: </strong></span>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<p>Production</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<span><strong>Version: </strong></span>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<p>v1.0</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withRouter(ApplicationView);
|
@ -1,132 +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 PropTypes from 'prop-types';
|
|
||||||
import Badge from 'material-ui/Badge';
|
|
||||||
import React, {Component} from 'react';
|
|
||||||
import AppBar from 'material-ui/AppBar';
|
|
||||||
import Drawer from 'material-ui/Drawer';
|
|
||||||
import IconButton from 'material-ui/IconButton';
|
|
||||||
import {List, ListItem} from 'material-ui/List';
|
|
||||||
import Apps from 'material-ui/svg-icons/navigation/apps';
|
|
||||||
import NotificationsIcon from 'material-ui/svg-icons/social/notifications';
|
|
||||||
import ActionAccountCircle from 'material-ui/svg-icons/action/account-circle';
|
|
||||||
import {Link, withRouter} from 'react-router-dom';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base Layout:
|
|
||||||
* App bar
|
|
||||||
* Left Navigation
|
|
||||||
* Middle content.
|
|
||||||
* */
|
|
||||||
class BaseLayout extends Component {
|
|
||||||
|
|
||||||
handleApplicationClick() {
|
|
||||||
this.handleHistory('/assets/apps');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The method to update the history.
|
|
||||||
* to: The URL to route.
|
|
||||||
* */
|
|
||||||
handleHistory(to) {
|
|
||||||
this.props.history.push(to);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleUserLogin() {
|
|
||||||
if (this.props.state.store.user) {
|
|
||||||
return (
|
|
||||||
<IconButton tooltip={this.props.state.store.user}>
|
|
||||||
<ActionAccountCircle/>
|
|
||||||
</IconButton>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<Link to='/login'> Login</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleNotification() {
|
|
||||||
if (this.props.state.store.user) {
|
|
||||||
return (
|
|
||||||
<Badge
|
|
||||||
badgeContent={this.props.state.store.notifications}
|
|
||||||
secondary={true}
|
|
||||||
badgeStyle={{top: 12, right: 12}}>
|
|
||||||
<IconButton tooltip="Notifications">
|
|
||||||
<NotificationsIcon/>
|
|
||||||
</IconButton>
|
|
||||||
</Badge>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<AppBar title="App Store"
|
|
||||||
iconElementRight={
|
|
||||||
<div>
|
|
||||||
{this.handleNotification()}
|
|
||||||
{this.handleUserLogin()}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<div>
|
|
||||||
<Drawer containerStyle={{height: 'calc(100% - 64px)', width: '15%', top: '13%', left: '1%'}}
|
|
||||||
open={true}>
|
|
||||||
<List>
|
|
||||||
<ListItem primaryText="Applications"
|
|
||||||
leftIcon={<Apps/>}
|
|
||||||
initiallyOpen={false}
|
|
||||||
primaryTogglesNestedList={true}
|
|
||||||
onClick={this.handleApplicationClick.bind(this)}
|
|
||||||
nestedItems={[
|
|
||||||
<ListItem
|
|
||||||
key={1}
|
|
||||||
primaryText="Business" //TODO: categoryies ...
|
|
||||||
leftIcon={<List/>}
|
|
||||||
/>]}
|
|
||||||
/>
|
|
||||||
</List>
|
|
||||||
</Drawer>
|
|
||||||
</div>
|
|
||||||
<div style=
|
|
||||||
{
|
|
||||||
{
|
|
||||||
height: 'calc(100% - 64px)',
|
|
||||||
marginLeft: '16%',
|
|
||||||
width: 'calc(100%-15%)',
|
|
||||||
top: 64,
|
|
||||||
left: "-100px"
|
|
||||||
}
|
|
||||||
}>
|
|
||||||
{this.props.children}
|
|
||||||
</div>
|
|
||||||
</div>);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseLayout.propTypes = {
|
|
||||||
children: PropTypes.element
|
|
||||||
};
|
|
||||||
|
|
||||||
export default withRouter(BaseLayout);
|
|
@ -1,168 +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 qs from 'qs';
|
|
||||||
import React, {Component} from 'react';
|
|
||||||
import Checkbox from 'material-ui/Checkbox';
|
|
||||||
import {Redirect, Route} from 'react-router-dom';
|
|
||||||
import RaisedButton from 'material-ui/RaisedButton';
|
|
||||||
import {Card, CardActions, CardTitle} from 'material-ui/Card';
|
|
||||||
import {TextValidator, ValidatorForm} from 'react-material-ui-form-validator';
|
|
||||||
import Store from '../App';
|
|
||||||
|
|
||||||
|
|
||||||
//todo: remove the {TextValidator, ValidatorForm} and implement it manually.
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Login Component.
|
|
||||||
*
|
|
||||||
* This component contains the Login form and methods to handle field change events.
|
|
||||||
* The user name and password will be set to the state and sent to the api.
|
|
||||||
*
|
|
||||||
* If the user is already logged in, it will redirect to the last point where the user was.
|
|
||||||
* */
|
|
||||||
class Login extends Component {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.state = {
|
|
||||||
isLoggedIn: false,
|
|
||||||
referrer: "/",
|
|
||||||
userName: "",
|
|
||||||
rememberMe: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
let queryString = this.props.location.search;
|
|
||||||
console.log(queryString);
|
|
||||||
queryString = queryString.replace(/^\?/, '');
|
|
||||||
/* With QS version up we can directly use {ignoreQueryPrefix: true} option */
|
|
||||||
let params = qs.parse(queryString);
|
|
||||||
if (params.referrer) {
|
|
||||||
this.setState({referrer: params.referrer});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleLogin(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
console.log(this.props);
|
|
||||||
//TODO: send authentication request.
|
|
||||||
let location = {
|
|
||||||
pathname: this.state.referrer
|
|
||||||
};
|
|
||||||
let storeState = {
|
|
||||||
store : {
|
|
||||||
user: this.state.userName,
|
|
||||||
notifications: 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.props.updateState(storeState);
|
|
||||||
this.props.history.push(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the username field change event.
|
|
||||||
* */
|
|
||||||
onUserNameChange(event) {
|
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
userName: event.target.value
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the password field change event.
|
|
||||||
* */
|
|
||||||
onPasswordChange(event) {
|
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
password: event.target.value
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the remember me check.
|
|
||||||
* */
|
|
||||||
handleRememberMe() {
|
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
rememberMe: !this.state.rememberMe
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSuccessfulLogin() {
|
|
||||||
return (
|
|
||||||
<Redirect to='/store'/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (!(this.state.isLoggedIn && this.state.userName)) {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
|
|
||||||
{/*TODO: Style the components.*/}
|
|
||||||
|
|
||||||
<Card>
|
|
||||||
<CardTitle title="WSO2 IoT App Store"/>
|
|
||||||
<CardActions>
|
|
||||||
<ValidatorForm
|
|
||||||
ref="form"
|
|
||||||
onSubmit={this.handleLogin.bind(this)}
|
|
||||||
onError={errors => console.log(errors)}>
|
|
||||||
<TextValidator
|
|
||||||
floatingLabelText="User Name"
|
|
||||||
floatingLabelFixed={true}
|
|
||||||
onChange={this.onUserNameChange.bind(this)}
|
|
||||||
name="userName"
|
|
||||||
validators={['required']}
|
|
||||||
errorMessages={['User Name is required']}
|
|
||||||
value={this.state.userName}
|
|
||||||
/>
|
|
||||||
<br/>
|
|
||||||
<TextValidator
|
|
||||||
floatingLabelText="Password"
|
|
||||||
floatingLabelFixed={true}
|
|
||||||
onChange={this.onPasswordChange.bind(this)}
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
value={this.state.password}
|
|
||||||
validators={['required']}
|
|
||||||
errorMessages={['Password is required']}
|
|
||||||
/>
|
|
||||||
<br/>
|
|
||||||
<Checkbox label="Remember me."
|
|
||||||
onCheck={this.handleRememberMe.bind(this)}
|
|
||||||
checked={this.state.rememberMe}/>
|
|
||||||
<br/>
|
|
||||||
<RaisedButton type="submit" label="Login"/>
|
|
||||||
</ValidatorForm>
|
|
||||||
</CardActions>
|
|
||||||
</Card>
|
|
||||||
</div>);
|
|
||||||
} else {
|
|
||||||
this.handleSuccessfulLogin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Login;
|
|
@ -0,0 +1,430 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Chip from 'material-ui/Chip';
|
||||||
|
import Dropzone from 'react-dropzone';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import Toggle from 'material-ui/Toggle';
|
||||||
|
import MenuItem from 'material-ui/MenuItem';
|
||||||
|
import TextField from 'material-ui/TextField';
|
||||||
|
import FlatButton from 'material-ui/FlatButton';
|
||||||
|
import IconButton from 'material-ui/IconButton';
|
||||||
|
import SelectField from 'material-ui/SelectField';
|
||||||
|
import RaisedButton from 'material-ui/RaisedButton';
|
||||||
|
import PlatformMgtApi from '../../api/platformMgtApi';
|
||||||
|
import Clear from 'material-ui/svg-icons/content/clear';
|
||||||
|
import {GridList, GridTile} from 'material-ui/GridList';
|
||||||
|
import Close from 'material-ui/svg-icons/navigation/close';
|
||||||
|
import {Card, CardActions, CardTitle} from 'material-ui/Card';
|
||||||
|
import AddCircleOutline from 'material-ui/svg-icons/content/add-circle-outline';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Platform Create component.
|
||||||
|
* Contains following components:
|
||||||
|
* * Platform Name
|
||||||
|
* * Platform Description
|
||||||
|
* * Platform Icon
|
||||||
|
* * Whether the platform needs an app to be installed.
|
||||||
|
* * Whether the platform is enabled by default.
|
||||||
|
* * Whether the platform is shared with tenants.
|
||||||
|
* */
|
||||||
|
class PlatformCreate extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.onCreatePlatform = this.onCreatePlatform.bind(this);
|
||||||
|
this.handleToggle = this.handleToggle.bind(this);
|
||||||
|
this.addProperty = this.addProperty.bind(this);
|
||||||
|
this.addTags = this.addTags.bind(this);
|
||||||
|
this.clearForm = this.clearForm.bind(this);
|
||||||
|
this.onPropertySelect = this.onPropertySelect.bind(this);
|
||||||
|
this.handleTagChange = this.handleTagChange.bind(this);
|
||||||
|
this.removeIcon = this.removeIcon.bind(this);
|
||||||
|
this.onTextChange = this.onTextChange.bind(this);
|
||||||
|
this.renderChip = this.renderChip.bind(this);
|
||||||
|
this.removeProperty = this.removeProperty.bind(this);
|
||||||
|
this.state = {
|
||||||
|
tags: [],
|
||||||
|
defValue: "",
|
||||||
|
enabled: true,
|
||||||
|
allTenants: false,
|
||||||
|
files: [],
|
||||||
|
platformProperties: [],
|
||||||
|
selectedProperty: 0,
|
||||||
|
name: "",
|
||||||
|
description: "",
|
||||||
|
property: "",
|
||||||
|
icon: [],
|
||||||
|
identifier: "",
|
||||||
|
propertyTypes: [
|
||||||
|
{key: 0, value: 'String'},
|
||||||
|
{key: 1, value: 'Number'},
|
||||||
|
{key: 2, value: 'Boolean'},
|
||||||
|
{key: 3, value: 'File'}]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles toggle button actions.
|
||||||
|
* One method is used for all the toggle buttons and, each toggle is identified by the id.
|
||||||
|
* */
|
||||||
|
handleToggle(event) {
|
||||||
|
switch (event.target.id) {
|
||||||
|
case "enabled" : {
|
||||||
|
let enabled = this.state.enabled;
|
||||||
|
this.setState({enabled: !enabled});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "tenant" : {
|
||||||
|
let allTenants = this.state.allTenants;
|
||||||
|
this.setState({allTenants: !allTenants});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers the onChange action on property type selection.
|
||||||
|
* */
|
||||||
|
onPropertySelect(event, index, value) {
|
||||||
|
console.log(this.state.propertyTypes[value]);
|
||||||
|
this.setState({selectedProperty: value});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles Chip delete function.
|
||||||
|
* Removes the tag from state.tags
|
||||||
|
* */
|
||||||
|
handleTagDelete(key) {
|
||||||
|
this.chipData = this.state.tags;
|
||||||
|
const chipToDelete = this.chipData.map((chip) => chip.key).indexOf(key);
|
||||||
|
this.chipData.splice(chipToDelete, 1);
|
||||||
|
this.setState({tags: this.chipData});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a tag on Enter key press and set it to the state.
|
||||||
|
* Clears the tags text field.
|
||||||
|
* Chip gets two parameters: Key and value.
|
||||||
|
* */
|
||||||
|
addTags(event) {
|
||||||
|
let tags = this.state.tags;
|
||||||
|
if (event.charCode === 13) {
|
||||||
|
event.preventDefault();
|
||||||
|
tags.push({key: Math.floor(Math.random() * 1000), value: event.target.value});
|
||||||
|
this.setState({tags, defValue: ""});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates Chip array from state.tags.
|
||||||
|
* */
|
||||||
|
renderChip(data) {
|
||||||
|
return (
|
||||||
|
<Chip
|
||||||
|
key={data.key}
|
||||||
|
onRequestDelete={() => this.handleTagDelete(data.key)}
|
||||||
|
style={this.styles.chip}
|
||||||
|
>
|
||||||
|
{data.value}
|
||||||
|
</Chip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value for tag.
|
||||||
|
* */
|
||||||
|
handleTagChange(event) {
|
||||||
|
let defaultValue = this.state.defValue;
|
||||||
|
defaultValue = event.target.value;
|
||||||
|
this.setState({defValue: defaultValue})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the selected property from the property list.
|
||||||
|
* */
|
||||||
|
removeProperty(property) {
|
||||||
|
let properties = this.state.platformProperties;
|
||||||
|
properties.splice(properties.indexOf(property), 1);
|
||||||
|
this.setState({platformProperties: properties});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new platform property.
|
||||||
|
* */
|
||||||
|
addProperty() {
|
||||||
|
let property = this.state.property;
|
||||||
|
let selected = this.state.selectedProperty;
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
platformProperties:
|
||||||
|
this.state.platformProperties.concat([
|
||||||
|
{
|
||||||
|
key: property,
|
||||||
|
value: this.state.propertyTypes[selected].value
|
||||||
|
}]),
|
||||||
|
property: "",
|
||||||
|
selectedProperty: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers in onChange event of text fields.
|
||||||
|
* Text fields are identified by their ids and the value will be persisted in the component state.
|
||||||
|
* */
|
||||||
|
onTextChange(event, value) {
|
||||||
|
let property = this.state.property;
|
||||||
|
let name = this.state.name;
|
||||||
|
let description = this.state.description;
|
||||||
|
let identifier = this.state.identifier;
|
||||||
|
|
||||||
|
switch (event.target.id) {
|
||||||
|
case "name": {
|
||||||
|
name = value;
|
||||||
|
this.setState({name: name});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case "description": {
|
||||||
|
description = value;
|
||||||
|
this.setState({description: description});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case "property": {
|
||||||
|
property = value;
|
||||||
|
this.setState({property: property});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "identifier": {
|
||||||
|
identifier = value;
|
||||||
|
this.setState({identifier: identifier});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create platform object and call the create platform api.
|
||||||
|
* */
|
||||||
|
onCreatePlatform(event) {
|
||||||
|
//Call the platform create api.
|
||||||
|
event.preventDefault();
|
||||||
|
let platform = {};
|
||||||
|
platform.identifier = this.state.identifier;
|
||||||
|
platform.name = this.state.name;
|
||||||
|
platform.description = this.state.description;
|
||||||
|
platform.tags = this.state.tags;
|
||||||
|
platform.properties = this.state.platformProperties;
|
||||||
|
platform.icon = this.state.icon;
|
||||||
|
platform.enabled = this.state.enabled;
|
||||||
|
platform.allTenants = this.state.allTenants;
|
||||||
|
platform.defaultTenantMapping = true;
|
||||||
|
|
||||||
|
PlatformMgtApi.createPlatform(platform);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the uploaded icon.
|
||||||
|
* */
|
||||||
|
removeIcon(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.setState({icon: []});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the user entered values in the form.
|
||||||
|
* */
|
||||||
|
clearForm(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.setState({
|
||||||
|
enabled: true,
|
||||||
|
allTenants: false,
|
||||||
|
files: [],
|
||||||
|
platformProperties: [],
|
||||||
|
selectedProperty: 0,
|
||||||
|
name: "",
|
||||||
|
description: "",
|
||||||
|
property: "",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
platformProperties,
|
||||||
|
allTenants,
|
||||||
|
enabled,
|
||||||
|
selectedProperty,
|
||||||
|
propertyTypes,
|
||||||
|
name,
|
||||||
|
tags,
|
||||||
|
defValue,
|
||||||
|
description,
|
||||||
|
identifier,
|
||||||
|
property
|
||||||
|
} = this.state;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="middle createplatformmiddle">
|
||||||
|
<Card>
|
||||||
|
<CardTitle title="Create Platform"/>
|
||||||
|
<CardActions>
|
||||||
|
<div className="createplatformcardaction">
|
||||||
|
<form>
|
||||||
|
<TextField
|
||||||
|
hintText="Unique Identifier for Platform."
|
||||||
|
id="identifier"
|
||||||
|
floatingLabelText="Identifier*"
|
||||||
|
floatingLabelFixed={true}
|
||||||
|
value={identifier}
|
||||||
|
onChange={this.onTextChange}
|
||||||
|
/>
|
||||||
|
<br/>
|
||||||
|
<TextField
|
||||||
|
hintText="Enter the Platform Name."
|
||||||
|
id="name"
|
||||||
|
floatingLabelText="Name*"
|
||||||
|
floatingLabelFixed={true}
|
||||||
|
value={name}
|
||||||
|
onChange={this.onTextChange}
|
||||||
|
/>
|
||||||
|
<br/>
|
||||||
|
<TextField
|
||||||
|
id="description"
|
||||||
|
hintText="Enter the Platform Description."
|
||||||
|
floatingLabelText="Description*"
|
||||||
|
floatingLabelFixed={true}
|
||||||
|
multiLine={true}
|
||||||
|
rows={2}
|
||||||
|
value={description}
|
||||||
|
onChange={this.onTextChange}
|
||||||
|
/>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<Toggle
|
||||||
|
id="tenant"
|
||||||
|
label="Shared with all Tenants"
|
||||||
|
labelPosition="right"
|
||||||
|
onToggle={this.handleToggle}
|
||||||
|
toggled={allTenants}
|
||||||
|
/>
|
||||||
|
<br/>
|
||||||
|
<Toggle
|
||||||
|
id="enabled"
|
||||||
|
label="Enabled"
|
||||||
|
labelPosition="right"
|
||||||
|
onToggle={this.handleToggle}
|
||||||
|
toggled={enabled}
|
||||||
|
/>
|
||||||
|
<br/>
|
||||||
|
<TextField
|
||||||
|
id="tags"
|
||||||
|
hintText="Enter Platform tags.."
|
||||||
|
floatingLabelText="Tags*"
|
||||||
|
floatingLabelFixed={true}
|
||||||
|
value={defValue}
|
||||||
|
onChange={this.handleTagChange}
|
||||||
|
onKeyPress={this.addTags}
|
||||||
|
/>
|
||||||
|
<br/>
|
||||||
|
<div className="createPlatformTagWrapper">
|
||||||
|
{tags.map(this.renderChip, this)}
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<div>
|
||||||
|
<p className="createplatformproperties">Platform Properties</p>
|
||||||
|
<div id="property-container">
|
||||||
|
{platformProperties.map((p) => {
|
||||||
|
return <div key={p.key}>{p.key} : {p.value}
|
||||||
|
<IconButton onClick={this.removeProperty.bind(this, p)}>
|
||||||
|
<Close className="createplatformpropertyclose"/>
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div className="createplatformproperty">
|
||||||
|
<TextField
|
||||||
|
id="property"
|
||||||
|
hintText="Property Name"
|
||||||
|
floatingLabelText="Platform Property*"
|
||||||
|
floatingLabelFixed={true}
|
||||||
|
value={this.state.property}
|
||||||
|
onChange={this.onTextChange}
|
||||||
|
/> <em/>
|
||||||
|
<SelectField
|
||||||
|
className="createplatformpropertyselect"
|
||||||
|
floatingLabelText="Property Type"
|
||||||
|
value={selectedProperty}
|
||||||
|
floatingLabelFixed={true}
|
||||||
|
onChange={this.onPropertySelect}>
|
||||||
|
{propertyTypes.map((type) => {
|
||||||
|
return <MenuItem key={type.key}
|
||||||
|
value={type.key}
|
||||||
|
primaryText={type.value}/>
|
||||||
|
})}
|
||||||
|
</SelectField>
|
||||||
|
<IconButton onClick={this.addProperty}>
|
||||||
|
<AddCircleOutline/>
|
||||||
|
</IconButton>
|
||||||
|
<br/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="createplatformiconp">Platform Icon*:</p>
|
||||||
|
<GridList className="createplatformicon" cols={1.1}>
|
||||||
|
{this.state.icon.map((tile) => (
|
||||||
|
<GridTile
|
||||||
|
key={Math.floor(Math.random() * 1000)}
|
||||||
|
title={tile.name}
|
||||||
|
actionIcon={
|
||||||
|
<IconButton onClick={this.removeIcon}>
|
||||||
|
<Clear/>
|
||||||
|
</IconButton>}>
|
||||||
|
<img src={tile.preview}/>
|
||||||
|
</GridTile>
|
||||||
|
))}
|
||||||
|
{this.state.icon.length === 0 ?
|
||||||
|
<Dropzone
|
||||||
|
className="createplatformdropzone"
|
||||||
|
accept="image/jpeg, image/png"
|
||||||
|
onDrop={(icon, rejected) => {
|
||||||
|
this.setState({icon, rejected})
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p className="createplatformdropzonep">+</p>
|
||||||
|
</Dropzone> : <div/>}
|
||||||
|
</GridList>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<RaisedButton
|
||||||
|
primary={true} label="Create"
|
||||||
|
onClick={this.onCreatePlatform}/>
|
||||||
|
<FlatButton label="Cancel" onClick={this.clearForm}/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</CardActions>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformCreate.prototypes = {};
|
||||||
|
|
||||||
|
export default PlatformCreate;
|
@ -0,0 +1,159 @@
|
|||||||
|
/*
|
||||||
|
* 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 {withRouter} from 'react-router-dom';
|
||||||
|
import TextField from 'material-ui/TextField';
|
||||||
|
import AuthHandler from "../../api/authHandler";
|
||||||
|
import DataTable from '../UIComponents/DataTable/DataTable';
|
||||||
|
import PlatformMgtApi from "../../api/platformMgtApi";
|
||||||
|
import {Card, CardActions, CardTitle} from 'material-ui/Card';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The App Create Component.
|
||||||
|
*
|
||||||
|
* Application creation is handled through a Wizard. (We use Material UI Stepper.)
|
||||||
|
*
|
||||||
|
* In each step, data will be set to the state separately.
|
||||||
|
* When the wizard is completed, data will be arranged and sent to the api.
|
||||||
|
* */
|
||||||
|
class PlatformListing extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.setPlatforms = this.setPlatforms.bind(this);
|
||||||
|
this.state = {
|
||||||
|
platforms: [],
|
||||||
|
asc: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
headers = [
|
||||||
|
{
|
||||||
|
data_id: "image",
|
||||||
|
data_type: "image",
|
||||||
|
sortable: false,
|
||||||
|
label: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "platformName",
|
||||||
|
data_type: String,
|
||||||
|
sortable: true,
|
||||||
|
label: "Platform Name",
|
||||||
|
sort: this.sortData
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "enabled",
|
||||||
|
data_type: String,
|
||||||
|
sortable: false,
|
||||||
|
label: "Enabled"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data_id: "fileBased",
|
||||||
|
data_type: String,
|
||||||
|
sortable: false,
|
||||||
|
label: "File Based"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
let platformsPromise = PlatformMgtApi.getPlatforms();
|
||||||
|
platformsPromise.then(
|
||||||
|
response => {
|
||||||
|
let platforms = this.setPlatforms(response.data);
|
||||||
|
this.setState({platforms: platforms});
|
||||||
|
}
|
||||||
|
).catch(
|
||||||
|
err => {
|
||||||
|
AuthHandler.unauthorizedErrorHandler(err);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create platform objects from the response which can be displayed in the table.
|
||||||
|
* */
|
||||||
|
setPlatforms(platforms) {
|
||||||
|
let tmpPlatforms = [];
|
||||||
|
|
||||||
|
for (let index in platforms) {
|
||||||
|
let platform = {};
|
||||||
|
platform.id = platforms[index].identifier;
|
||||||
|
platform.platformName = platforms[index].name;
|
||||||
|
platform.enabled = platforms[index].enabled.toString();
|
||||||
|
platform.fileBased = platforms[index].fileBased.toString();
|
||||||
|
tmpPlatforms.push(platform)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmpPlatforms;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the search action.
|
||||||
|
* When typing in the search bar, this method will be invoked.
|
||||||
|
* */
|
||||||
|
searchApplications(word) {
|
||||||
|
let searchedData = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles sort data function and toggles the asc state.
|
||||||
|
* asc: true : sort in ascending order.
|
||||||
|
* */
|
||||||
|
sortData() {
|
||||||
|
let isAsc = this.state.asc;
|
||||||
|
let datas = isAsc ? this.data.sort(this.compare) : this.data.reverse();
|
||||||
|
this.setState({data: datas, asc: !isAsc});
|
||||||
|
}
|
||||||
|
|
||||||
|
compare(a, b) {
|
||||||
|
if (a.applicationName < b.applicationName)
|
||||||
|
return -1;
|
||||||
|
if (a.applicationName > b.applicationName)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
onRowClick(id) {
|
||||||
|
//TODO: Remove this
|
||||||
|
console.log(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className='middle listingplatformmiddle'>
|
||||||
|
<Card className='listingplatformcard'>
|
||||||
|
<TextField hintText="Search" onChange={this.searchApplications.bind(this)}
|
||||||
|
className='listingplatformsearch'/>
|
||||||
|
<CardTitle title="Platforms" className='listingplatformTitle'/>
|
||||||
|
<CardActions>
|
||||||
|
|
||||||
|
</CardActions>
|
||||||
|
<DataTable
|
||||||
|
headers={this.headers}
|
||||||
|
data={this.state.platforms}
|
||||||
|
handleRowClick={this.onRowClick.bind(this)}
|
||||||
|
noDataMessage={{type: 'button', text: 'Create Platform'}}/>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformListing.propTypes = {};
|
||||||
|
|
||||||
|
export default withRouter(PlatformListing);
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Platform view component.
|
||||||
|
* */
|
||||||
|
class PlatformView extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
Platform View
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlatformView;
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Review Listing.
|
||||||
|
* */
|
||||||
|
class ReviewListing extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
Reviews List
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReviewListing;
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Review details view.
|
||||||
|
* */
|
||||||
|
class ReviewView extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
Review
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReviewView;
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import Theme from '../../../theme';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component for holding uploaded image.
|
||||||
|
* This component has the feature to remove selected image from the array.
|
||||||
|
* */
|
||||||
|
class AppImage extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.removeImage = this.removeImage.bind(this);
|
||||||
|
this.scriptId = "appImage";
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
/**
|
||||||
|
*Loading the theme files based on the the user-preference.
|
||||||
|
*/
|
||||||
|
Theme.insertThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
Theme.removeThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers the parent method to remove the selected image.
|
||||||
|
* @param event: The click event of the component.
|
||||||
|
* */
|
||||||
|
removeImage(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.props.onRemove(event.target.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {image, imageId} = this.props;
|
||||||
|
return (
|
||||||
|
<div className="image-container" style={this.props.imageStyles}>
|
||||||
|
<img src={image} className="image" id={imageId}/>
|
||||||
|
<div className="btn-content">
|
||||||
|
<i className="close-btn" id={imageId} onClick={this.removeImage}>X</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AppImage.propTypes = {
|
||||||
|
image: PropTypes.string,
|
||||||
|
imageId: PropTypes.string,
|
||||||
|
onRemove: PropTypes.func,
|
||||||
|
imageStyles: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AppImage;
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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 Theme from '../../../theme';
|
||||||
|
|
||||||
|
class Chip extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.scriptId = "chip";
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
/**
|
||||||
|
*Loading the theme files based on the the user-preference.
|
||||||
|
*/
|
||||||
|
Theme.insertThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
Theme.removeThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="chip">
|
||||||
|
{this.props.image?<img src={this.props.image} alt="Person" width="96" height="96" />:<div/>}
|
||||||
|
{this.props.text}
|
||||||
|
<span className="close-btn" >×</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Chip;
|
@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* 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 Theme from '../../../theme';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import DataTableRow from './DataTableRow';
|
||||||
|
import DataTableHeader from './DataTableHeader';
|
||||||
|
import RaisedButton from 'material-ui/RaisedButton';
|
||||||
|
import {Table, TableBody, TableHeader, TableRow} from 'material-ui/Table';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Custom Table Component.
|
||||||
|
* This component wraps the material-ui Table component and add some extra functionalities.
|
||||||
|
* 1. Table header click. (For sorting)
|
||||||
|
* 2. Table row click.
|
||||||
|
*
|
||||||
|
* The main sort function is defined in the component where the data table is created and passed to the
|
||||||
|
* DataTable component via props.
|
||||||
|
*
|
||||||
|
* Following are the DataTable proptypes.
|
||||||
|
* 1. Headers: Table headers. This is an array of Json Objects.
|
||||||
|
* An Header Object contains the properties of each header. Currently following properties
|
||||||
|
* are supported.
|
||||||
|
* * sortable: boolean : whether the table column is sortable or not.
|
||||||
|
* * sort: func : If sortable, the sort function.
|
||||||
|
* * sort: func : If sortable, the sort function.
|
||||||
|
* * sort: func : If sortable, the sort function.
|
||||||
|
* * label: String: The Table header string.
|
||||||
|
* * id: String: Unique id for header.
|
||||||
|
*
|
||||||
|
* 2. Data: The list of data that needs to be displayed in the table.
|
||||||
|
* This is also a json array of data objects.
|
||||||
|
* The Json object should contain key: value pair where the key is the header id.
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
class DataTable extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.handleRowClick = this.handleRowClick.bind(this);
|
||||||
|
this.handleBtnClick = this.handleBtnClick.bind(this);
|
||||||
|
this.state = {
|
||||||
|
data: [],
|
||||||
|
headers: [],
|
||||||
|
};
|
||||||
|
this.scriptId = "data-table"
|
||||||
|
};
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
console.log("Will mount", this.props.data); //TODO: Remove this
|
||||||
|
this.setState({data: this.props.data, headers: this.props.headers}, Theme.insertThemingScripts(this.scriptId));
|
||||||
|
|
||||||
|
/**
|
||||||
|
*Loading the theme files based on the the user-preference.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
Theme.removeThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
if (!nextProps.data) {
|
||||||
|
this.setState({data: nextState.data});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
this.setState({data: nextProps.data});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers when user click on table row.
|
||||||
|
* This method invokes the parent method handleRowClick, which is passed via props.
|
||||||
|
* */
|
||||||
|
handleRowClick(id) {
|
||||||
|
this.props.handleRowClick(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBtnClick(id) {
|
||||||
|
this.props.handleButtonClick(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {data, headers} = this.state;
|
||||||
|
|
||||||
|
//TODO: Remove this
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
let noDataContent = null;
|
||||||
|
|
||||||
|
if (this.props.noDataMessage.type === 'button') {
|
||||||
|
noDataContent = <div><RaisedButton label={this.props.noDataMessage.text}/></div>
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
return (<Table
|
||||||
|
selectable={false}>
|
||||||
|
<TableHeader displaySelectAll={false} adjustForCheckbox={false}>
|
||||||
|
<TableRow>
|
||||||
|
{headers.map((header) => {
|
||||||
|
return (
|
||||||
|
<DataTableHeader
|
||||||
|
key={header.data_id}
|
||||||
|
className="datatableRowColumn"
|
||||||
|
header={header}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
)}
|
||||||
|
</TableRow>
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{data.map((dataItem) => {
|
||||||
|
return (
|
||||||
|
<DataTableRow
|
||||||
|
key={dataItem.id}
|
||||||
|
dataItem={dataItem}
|
||||||
|
handleButtonClick={this.handleBtnClick}
|
||||||
|
handleClick={this.handleRowClick}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>)
|
||||||
|
}
|
||||||
|
return (<div>{noDataContent}</div>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataTable.prototypes = {
|
||||||
|
data: PropTypes.arrayOf(Object),
|
||||||
|
headers: PropTypes.arrayOf(Object),
|
||||||
|
sortData: PropTypes.func,
|
||||||
|
handleRowClick: PropTypes.func,
|
||||||
|
noDataMessage: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DataTable;
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* 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 Theme from '../../../theme';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import FlatButton from 'material-ui/FlatButton';
|
||||||
|
import {TableHeaderColumn} from 'material-ui/Table';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data Table header component.
|
||||||
|
* This component creates the header elements of the table.
|
||||||
|
* */
|
||||||
|
class DataTableHeader extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.tableHeaderClick = this.tableHeaderClick.bind(this);
|
||||||
|
this.scriptId = "data-table";
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
/**
|
||||||
|
*Loading the theme files based on the the user-preference.
|
||||||
|
*/
|
||||||
|
Theme.insertThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
Theme.removeThemingScripts(this.scriptId);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The onClick function of the table header.
|
||||||
|
* Invokes the function passed in the header object.
|
||||||
|
* */
|
||||||
|
tableHeaderClick() {
|
||||||
|
this.props.header.sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let headerCell = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the header is sortable, create a button with onClick handler.
|
||||||
|
* else create a span element with label as the table header.
|
||||||
|
* */
|
||||||
|
if (this.props.header.sortable) {
|
||||||
|
headerCell =
|
||||||
|
<FlatButton
|
||||||
|
label={this.props.header.label}
|
||||||
|
onClick={this.tableHeaderClick}
|
||||||
|
className="sortableHeaderCell"
|
||||||
|
/>
|
||||||
|
} else {
|
||||||
|
headerCell = <span className="notsortableHeaderCell">{this.props.header.label}</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableHeaderColumn key={this.props.header.id} className="datatableHeaderColumn">
|
||||||
|
{headerCell}
|
||||||
|
</TableHeaderColumn>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataTableHeader.prototypes = {
|
||||||
|
header: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DataTableHeader;
|
@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Theme from '../../../theme';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import IconButton from 'material-ui/IconButton';
|
||||||
|
import Create from 'material-ui/svg-icons/content/create'
|
||||||
|
import {TableRow, TableRowColumn} from 'material-ui/Table';
|
||||||
|
import Avatar from 'material-ui/Avatar';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data table row component.
|
||||||
|
* This component created a row in the data table according to the props.
|
||||||
|
* */
|
||||||
|
class DataTableRow extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.state = {
|
||||||
|
dataItem: {}
|
||||||
|
};
|
||||||
|
this.scriptId = "data-table";
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.setState({dataItem: this.props.dataItem});
|
||||||
|
|
||||||
|
/**
|
||||||
|
*Loading the theme files based on the the user-preference.
|
||||||
|
*/
|
||||||
|
Theme.insertThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
Theme.removeThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers the click event on the data table row.
|
||||||
|
* */
|
||||||
|
handleClick(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
this.props.handleClick(this.state.dataItem.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBtnClick(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
console.log(event.target['id'])
|
||||||
|
this.props.handleButtonClick(event.target['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {dataItem} = this.state;
|
||||||
|
return (
|
||||||
|
<TableRow
|
||||||
|
key={this.props.key}
|
||||||
|
onClick={this.handleClick.bind(this)}
|
||||||
|
>
|
||||||
|
<TableRowColumn
|
||||||
|
className="datatableRowColumn"
|
||||||
|
key={Math.random()}
|
||||||
|
>
|
||||||
|
<Avatar>{dataItem.name}</Avatar>
|
||||||
|
</TableRowColumn>
|
||||||
|
{Object.keys(dataItem).map((key) => {
|
||||||
|
if (key !== 'id') {
|
||||||
|
return (
|
||||||
|
<TableRowColumn
|
||||||
|
className="datatableRowColumn"
|
||||||
|
key={key}
|
||||||
|
>
|
||||||
|
{dataItem[key]}
|
||||||
|
</TableRowColumn>)
|
||||||
|
}
|
||||||
|
|
||||||
|
})}
|
||||||
|
<TableRowColumn
|
||||||
|
className="datatableRowColumn"
|
||||||
|
key={dataItem.id}
|
||||||
|
>
|
||||||
|
<IconButton id={dataItem.id} onClick={this.handleBtnClick.bind(this)}>
|
||||||
|
<Create id={dataItem.id}/>
|
||||||
|
</IconButton>
|
||||||
|
</TableRowColumn>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataTableRow.propTypes = {
|
||||||
|
onClick: PropTypes.func,
|
||||||
|
data: PropTypes.object
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DataTableRow;
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import Theme from '../../../theme'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom React component for Application View.
|
||||||
|
* */
|
||||||
|
class Drawer extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.closeDrawer = this.closeDrawer.bind(this);
|
||||||
|
this.scriptId = "drawer";
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
/**
|
||||||
|
*Loading the theme files based on the the user-preference.
|
||||||
|
*/
|
||||||
|
Theme.insertThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
Theme.removeThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the drawer.
|
||||||
|
* */
|
||||||
|
closeDrawer() {
|
||||||
|
this.props.onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div id="app-view" className="app-view-drawer" style={this.props.style}>
|
||||||
|
<a onClick={this.closeDrawer} className="drawer-close-btn"><i className="fw fw-uncheck"></i></a>
|
||||||
|
{this.props.children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Drawer.propTypes = {
|
||||||
|
style: PropTypes.object,
|
||||||
|
children: PropTypes.node,
|
||||||
|
onClose: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Drawer;
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import Theme from '../../../theme';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Floating Action button.
|
||||||
|
* */
|
||||||
|
class FloatingButton extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.scriptId = "floatingButton";
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
/**
|
||||||
|
*Loading the theme files based on the the user-preference.
|
||||||
|
*/
|
||||||
|
Theme.insertThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
Theme.removeThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick(event) {
|
||||||
|
this.props.onClick(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let classes = 'btn-circle ' + this.props.className;
|
||||||
|
return (
|
||||||
|
<div className={classes} onClick={this.handleClick.bind(this)}>
|
||||||
|
<i className="fw fw-add"></i>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FloatingButton.propTypes = {
|
||||||
|
classNames: PropTypes.string,
|
||||||
|
onClick: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FloatingButton;
|
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. licenses this file to you under the Apache License,
|
||||||
|
* Version 2.0 (the "License"); you may not use this file except
|
||||||
|
* in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import Dropzone from "react-dropzone";
|
||||||
|
import {Row} from "reactstrap";
|
||||||
|
import Theme from '../../../theme';
|
||||||
|
|
||||||
|
|
||||||
|
class ImageUploader extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.setImages = this.setImages.bind(this);
|
||||||
|
this.state = {
|
||||||
|
images: []
|
||||||
|
};
|
||||||
|
this.scriptId = "imageUploader";
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
/**
|
||||||
|
*Loading the theme files based on the the user-preference.
|
||||||
|
*/
|
||||||
|
Theme.insertThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
Theme.removeThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
setImages(images) {
|
||||||
|
this.props.setImages(images);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let {images, height, width, accepted, multiple, maxAmount} = this.props;
|
||||||
|
return (
|
||||||
|
<div id="screenshot-container">
|
||||||
|
<Row>
|
||||||
|
{images.map((tile) => (
|
||||||
|
<input type="image" src={tile[0].preview} onClick=""/>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
{this.state.screenshots.length < maxAmount ?
|
||||||
|
<Dropzone
|
||||||
|
className="add-image"
|
||||||
|
accept="image/jpeg, image/png"
|
||||||
|
onDrop={(accepted, rejected) => {
|
||||||
|
this.setImages(accepted);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p className="add-image-symbol">+</p>
|
||||||
|
</Dropzone> : <div/>}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageUploader.prototypes = {
|
||||||
|
height: PropTypes.string,
|
||||||
|
width: PropTypes.string,
|
||||||
|
accepted: PropTypes.array,
|
||||||
|
multiple: PropTypes.bool,
|
||||||
|
maxAmount: PropTypes.number,
|
||||||
|
setImages: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default ImageUploader;
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* 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 {Col, Row} from "reactstrap";
|
||||||
|
import Theme from '../../../theme'
|
||||||
|
|
||||||
|
class NotificationItem extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.scriptId = "notification";
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
/**
|
||||||
|
*Loading the theme files based on the the user-preference.
|
||||||
|
*/
|
||||||
|
Theme.insertThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
Theme.removeThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Row>
|
||||||
|
<Col>
|
||||||
|
<div className="notification-app-icon small">
|
||||||
|
<img/>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col>
|
||||||
|
<p>Your application, Facebook has been published.</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NotificationItem;
|
@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* 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 {Col, Row} from "reactstrap";
|
||||||
|
import './notification.css';
|
||||||
|
import Theme from '../../../theme'
|
||||||
|
|
||||||
|
class NotificationView extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.scriptId = "notification";
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
/**
|
||||||
|
*Loading the theme files based on the the user-preference.
|
||||||
|
*/
|
||||||
|
Theme.insertThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
Theme.removeThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div id="notification-view-content">
|
||||||
|
<div>
|
||||||
|
<Row id="notification-content">
|
||||||
|
<Col xs="3">
|
||||||
|
<div className="notification-app-icon medium">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
<Col xs="9">
|
||||||
|
<Row>
|
||||||
|
<span><strong>Application Name</strong></span>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<span>Version 1.0</span>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<p id="app-reject-msg">Your Application was rejected</p>
|
||||||
|
</Row>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<hr/>
|
||||||
|
<Row id="notification-content">
|
||||||
|
<Col xs="12">
|
||||||
|
<p>Following validations were detected in your review submission.
|
||||||
|
Please attend to them and re-submit</p>
|
||||||
|
<ul>
|
||||||
|
<li>sdjjfsdfsdfkjs shdfjhlkds hflkhfdslkd </li>
|
||||||
|
<li>sdfkds jfdsljfklsdfjksdjlksdjdlkf</li>
|
||||||
|
<li>sfksdf slkjskd jfjds lkfjdsfdsfdslkf sjf lkdsf</li>
|
||||||
|
<li>skfjslkdjfsdjfjksldjf sdkl jflkds jfkslfjs</li>
|
||||||
|
<li>ksdf jks;kshflk hlkjhds lkjhdsklhsd lkf</li>
|
||||||
|
<li> jsdljflksd jfklsdfskljfkjshf;ks ldj</li>
|
||||||
|
</ul>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NotificationView;
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* 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 Theme from '../../../theme';
|
||||||
|
|
||||||
|
class Switch extends Component {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.scriptId = "switch";
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
/**
|
||||||
|
*Loading the theme files based on the the user-preference.
|
||||||
|
*/
|
||||||
|
Theme.insertThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
Theme.removeThemingScripts(this.scriptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {height, width} = this.props;
|
||||||
|
return (
|
||||||
|
<label className="switch">
|
||||||
|
<input type="checkbox" onChange={this.props.onChange}/>
|
||||||
|
<span className="slider round"></span>
|
||||||
|
</label>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Switch;
|
@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* 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 qs from 'qs';
|
||||||
|
import React, {Component} from 'react';
|
||||||
|
import {Redirect, Switch} from 'react-router-dom';
|
||||||
|
import AuthHandler from '../../../api/authHandler';
|
||||||
|
import {Button, Card, CardBlock, CardTitle, Col, Form, FormGroup, Input, Label} from 'reactstrap';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Login Component.
|
||||||
|
*
|
||||||
|
* This component contains the Login form and methods to handle field change events.
|
||||||
|
* The user name and password will be set to the state and sent to the api.
|
||||||
|
*
|
||||||
|
* If the user is already logged in, it will redirect to the last point where the user was.
|
||||||
|
* */
|
||||||
|
class Login extends Component {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.state = {
|
||||||
|
isLoggedIn: false,
|
||||||
|
referrer: "/",
|
||||||
|
userName: "",
|
||||||
|
password: "",
|
||||||
|
rememberMe: true,
|
||||||
|
errors: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
let queryString = this.props.location.search;
|
||||||
|
console.log(queryString);
|
||||||
|
queryString = queryString.replace(/^\?/, '');
|
||||||
|
/* With QS version up we can directly use {ignoreQueryPrefix: true} option */
|
||||||
|
let params = qs.parse(queryString);
|
||||||
|
if (params.referrer) {
|
||||||
|
this.setState({referrer: params.referrer});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLogin(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
this.validateForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the username field change event.
|
||||||
|
* */
|
||||||
|
onUserNameChange(event, value) {
|
||||||
|
console.log(event.target.value);
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
userName: event.target.value
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the password field change event.
|
||||||
|
* */
|
||||||
|
onPasswordChange(event, value) {
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
password: event.target.value
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the remember me check.
|
||||||
|
* */
|
||||||
|
handleRememberMe() {
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
rememberMe: !this.state.rememberMe
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the login form.
|
||||||
|
* */
|
||||||
|
validateForm() {
|
||||||
|
let errors = {};
|
||||||
|
let validationFailed = true;
|
||||||
|
if (!this.state.password) {
|
||||||
|
errors["passwordError"] = "Password is Required";
|
||||||
|
validationFailed = true;
|
||||||
|
} else {
|
||||||
|
validationFailed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.state.userName) {
|
||||||
|
errors["userNameError"] = "User Name is Required";
|
||||||
|
validationFailed = true;
|
||||||
|
} else {
|
||||||
|
validationFailed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validationFailed) {
|
||||||
|
this.setState({errors: errors}, console.log(errors));
|
||||||
|
} else {
|
||||||
|
let loginPromis = AuthHandler.login(this.state.userName, this.state.password);
|
||||||
|
loginPromis.then(response => {
|
||||||
|
console.log(AuthHandler.getUser());
|
||||||
|
this.setState({isLoggedIn: AuthHandler.getUser()});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
if (!this.state.isLoggedIn) {
|
||||||
|
return (
|
||||||
|
<div id="login-container">
|
||||||
|
{/*TODO: Style the components.*/}
|
||||||
|
<Card id="login-card">
|
||||||
|
<CardBlock>
|
||||||
|
<CardTitle>WSO2 IoT APP Publisher</CardTitle>
|
||||||
|
<Form onSubmit={this.handleLogin.bind(this)}>
|
||||||
|
<FormGroup row>
|
||||||
|
<Label for="userName" sm={2}>User Name:</Label>
|
||||||
|
<Col sm={10}>
|
||||||
|
<Input type="text" name="userName" id="userName" placeholder="User Name"
|
||||||
|
onChange={this.onUserNameChange.bind(this)}/>
|
||||||
|
</Col>
|
||||||
|
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup row>
|
||||||
|
<Label for="password" sm={2}>Password:</Label>
|
||||||
|
<Col sm={10}>
|
||||||
|
<Input type="password" name="text" id="password" placeholder="Password"
|
||||||
|
onChange={this.onPasswordChange.bind(this)}/>
|
||||||
|
</Col>
|
||||||
|
</FormGroup>
|
||||||
|
<FormGroup check row>
|
||||||
|
<Col sm={{size: 10, offset: 2}}>
|
||||||
|
<Button type="submit" id="login-btn">Login</Button>
|
||||||
|
</Col>
|
||||||
|
</FormGroup>
|
||||||
|
</Form>
|
||||||
|
</CardBlock>
|
||||||
|
</Card>
|
||||||
|
</div>);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Switch>
|
||||||
|
<Redirect to={this.state.referrer}/>
|
||||||
|
</Switch>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Login;
|
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"theme" : {
|
"theme": {
|
||||||
"current" : "default",
|
"type": "default",
|
||||||
"default" : "lightBaseTheme",
|
"value": "lightBaseTheme"
|
||||||
"custom" : "custom-theme"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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 from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import Store from './App';
|
import Store from './App';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import 'bootstrap/dist/css/bootstrap.css';
|
||||||
|
import registerServiceWorker from './registerServiceWorker';
|
||||||
|
|
||||||
ReactDOM.render(<Store />, document.getElementById('root'));
|
/**
|
||||||
|
* This is the base js file of the app. All the content will be rendered in the root element.
|
||||||
|
* */
|
||||||
|
ReactDOM.render(<Store/>, document.getElementById('root'));
|
||||||
|
registerServiceWorker();
|
||||||
|
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// In production, we register a service worker to serve assets from local cache.
|
||||||
|
|
||||||
|
// This lets the app load faster on subsequent visits in production, and gives
|
||||||
|
// it offline capabilities. However, it also means that developers (and users)
|
||||||
|
// will only see deployed updates on the "N+1" visit to a page, since previously
|
||||||
|
// cached resources are updated in the background.
|
||||||
|
|
||||||
|
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
|
||||||
|
// This link also includes instructions on opting out of this behavior.
|
||||||
|
|
||||||
|
const isLocalhost = Boolean(
|
||||||
|
window.location.hostname === 'localhost' ||
|
||||||
|
// [::1] is the IPv6 localhost address.
|
||||||
|
window.location.hostname === '[::1]' ||
|
||||||
|
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||||
|
window.location.hostname.match(
|
||||||
|
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
export default function register() {
|
||||||
|
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||||
|
// The URL constructor is available in all browsers that support SW.
|
||||||
|
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
|
||||||
|
if (publicUrl.origin !== window.location.origin) {
|
||||||
|
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||||
|
// from what our page is served on. This might happen if a CDN is used to
|
||||||
|
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
const swUrl = `${process.env.PUBLIC_URL}/publisher/service-worker.js`;
|
||||||
|
|
||||||
|
if (!isLocalhost) {
|
||||||
|
// Is not local host. Just register service worker
|
||||||
|
registerValidSW(swUrl);
|
||||||
|
} else {
|
||||||
|
// This is running on localhost. Lets check if a service worker still exists or not.
|
||||||
|
checkValidServiceWorker(swUrl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function registerValidSW(swUrl) {
|
||||||
|
navigator.serviceWorker
|
||||||
|
.register(swUrl)
|
||||||
|
.then(registration => {
|
||||||
|
registration.onupdatefound = () => {
|
||||||
|
const installingWorker = registration.installing;
|
||||||
|
installingWorker.onstatechange = () => {
|
||||||
|
if (installingWorker.state === 'installed') {
|
||||||
|
if (navigator.serviceWorker.controller) {
|
||||||
|
// At this point, the old content will have been purged and
|
||||||
|
// the fresh content will have been added to the cache.
|
||||||
|
// It's the perfect time to display a "New content is
|
||||||
|
// available; please refresh." message in your web app.
|
||||||
|
console.log('New content is available; please refresh.');
|
||||||
|
} else {
|
||||||
|
// At this point, everything has been precached.
|
||||||
|
// It's the perfect time to display a
|
||||||
|
// "Content is cached for offline use." message.
|
||||||
|
console.log('Content is cached for offline use.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error during service worker registration:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkValidServiceWorker(swUrl) {
|
||||||
|
// Check if the service worker can be found. If it can't reload the page.
|
||||||
|
fetch(swUrl)
|
||||||
|
.then(response => {
|
||||||
|
// Ensure service worker exists, and that we really are getting a JS file.
|
||||||
|
if (
|
||||||
|
response.status === 404 ||
|
||||||
|
response.headers.get('content-type').indexOf('javascript') === -1
|
||||||
|
) {
|
||||||
|
// No service worker found. Probably a different app. Reload the page.
|
||||||
|
navigator.serviceWorker.ready.then(registration => {
|
||||||
|
registration.unregister().then(() => {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Service worker found. Proceed as normal.
|
||||||
|
registerValidSW(swUrl);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
console.log(
|
||||||
|
'No internet connection found. App is running in offline mode.'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function unregister() {
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
navigator.serviceWorker.ready.then(registration => {
|
||||||
|
registration.unregister();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* 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 axios from 'axios';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class will read through the configuration file and saves the theme names for the usage in other files.
|
||||||
|
* User can define the themes in the config.json. The themes will be loaded based on the user preference.
|
||||||
|
*/
|
||||||
|
class Theme {
|
||||||
|
constructor() {
|
||||||
|
this.defaultThemeType = "default";
|
||||||
|
this.currentThemeType = this.defaultThemeType;
|
||||||
|
this.currentTheme = "lightBaseTheme";
|
||||||
|
this.themeFolder = "themes";
|
||||||
|
this.styleSheetType = "text/css";
|
||||||
|
this.styleSheetRel = "stylesheet";
|
||||||
|
this.selectedTheme = this.defaultThemeType;
|
||||||
|
|
||||||
|
//TODO Need to get the app context properly when the server is ready
|
||||||
|
this.baseURL = window.location.origin;
|
||||||
|
this.appContext = window.location.pathname.split("/")[1];
|
||||||
|
this.loadThemeConfigs = this.loadThemeConfigs.bind(this);
|
||||||
|
this.loadThemeFiles = this.loadThemeFiles.bind(this);
|
||||||
|
this.insertThemingScripts = this.insertThemingScripts.bind(this);
|
||||||
|
this.removeThemingScripts = this.removeThemingScripts.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To load the theme related configurations from the configuration file.
|
||||||
|
* @returns the http response.
|
||||||
|
*/
|
||||||
|
loadThemeConfigs () {
|
||||||
|
let httpClient = axios.create({
|
||||||
|
baseURL: this.baseURL + "/" + this.appContext + "/config.json",
|
||||||
|
timeout: 2000
|
||||||
|
});
|
||||||
|
httpClient.defaults.headers.post['Content-Type'] = 'application/json';
|
||||||
|
return httpClient.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To load the particular theme file from the path.
|
||||||
|
* @param path Path to load the theme files
|
||||||
|
* @returns Http response from the particular file.
|
||||||
|
*/
|
||||||
|
loadThemeFiles (path) {
|
||||||
|
let httpClient = axios.create({
|
||||||
|
baseURL: this.baseURL + "/" + this.appContext + path,
|
||||||
|
timeout: 2000
|
||||||
|
});
|
||||||
|
return httpClient.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To insert the css files to the document.
|
||||||
|
* @param scriptId ID of the script that need to be inserted
|
||||||
|
*/
|
||||||
|
insertThemingScripts(scriptId) {
|
||||||
|
const script = scriptId + ".css";
|
||||||
|
let themePath = "/" + this.themeFolder + "/" + this.selectedTheme + "/" + script;
|
||||||
|
let themeFile = this.loadThemeFiles(themePath);
|
||||||
|
let head = document.getElementsByTagName("head")[0];
|
||||||
|
let link = document.createElement("link");
|
||||||
|
link.type = this.styleSheetType;
|
||||||
|
link.href = this.baseURL + "/" + this.appContext + themePath;
|
||||||
|
link.id = scriptId;
|
||||||
|
link.rel = this.styleSheetRel;
|
||||||
|
this.removeThemingScripts(scriptId);
|
||||||
|
|
||||||
|
themeFile.then(function () {
|
||||||
|
head.appendChild(link);
|
||||||
|
}).catch(error => {
|
||||||
|
// If there is no customized css file, load the default one.
|
||||||
|
themePath = "/" + this.themeFolder + "/" + this.defaultThemeType + "/" + script;
|
||||||
|
link.href = this.baseURL + "/" + this.appContext + themePath;
|
||||||
|
head.appendChild(link);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To remove the css scripts that are inserted before.
|
||||||
|
* @param scriptId Id of the script that need to be removed
|
||||||
|
*/
|
||||||
|
removeThemingScripts(scriptId) {
|
||||||
|
let styleSheet = document.getElementById(scriptId);
|
||||||
|
if (styleSheet !== null) {
|
||||||
|
styleSheet.disabled = true;
|
||||||
|
styleSheet.parentNode.removeChild(styleSheet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default (new Theme);
|
Loading…
Reference in new issue