mirror of
https://repository.entgra.net/community/device-mgt-core.git
synced 2025-10-06 02:01:45 +00:00
Merge branch 'application-mgt-new' of gitlab.com:entgra/carbon-device-mgt into application-mgt-new
This commit is contained in:
commit
3135d71a52
@ -47,15 +47,16 @@
|
||||
</context-param>
|
||||
|
||||
<!-- Below configuration is used to redirect http requests to https -->
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>ApplicationMgt-Admin</web-resource-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</web-resource-collection>
|
||||
<user-data-constraint>
|
||||
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
|
||||
</user-data-constraint>
|
||||
</security-constraint>
|
||||
<!-- Below configuration is commented because artifact download API is accessed from the device -->
|
||||
<!-- <security-constraint>-->
|
||||
<!-- <web-resource-collection>-->
|
||||
<!-- <web-resource-name>ApplicationMgt-Admin</web-resource-name>-->
|
||||
<!-- <url-pattern>/*</url-pattern>-->
|
||||
<!-- </web-resource-collection>-->
|
||||
<!-- <user-data-constraint>-->
|
||||
<!-- <transport-guarantee>CONFIDENTIAL</transport-guarantee>-->
|
||||
<!-- </user-data-constraint>-->
|
||||
<!-- </security-constraint>-->
|
||||
|
||||
<!--publish to apim-->
|
||||
<context-param>
|
||||
|
||||
@ -50,6 +50,7 @@ import org.wso2.carbon.device.application.mgt.core.util.HelperUtil;
|
||||
import org.wso2.carbon.device.mgt.common.Device;
|
||||
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
|
||||
import org.wso2.carbon.device.mgt.common.app.mgt.MobileApp;
|
||||
import org.wso2.carbon.device.mgt.common.app.mgt.MobileAppTypes;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException;
|
||||
import org.wso2.carbon.device.mgt.common.exceptions.UnknownApplicationTypeException;
|
||||
@ -458,8 +459,11 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
|
||||
|
||||
//todo rethink and modify the {@link MobileApp} usage
|
||||
MobileApp mobileApp = new MobileApp();
|
||||
MobileAppTypes mobileAppType = MobileAppTypes.valueOf(application.getType());
|
||||
if (DeviceTypes.ANDROID.toString().equalsIgnoreCase(deviceType)) {
|
||||
if (SubAction.INSTALL.toString().equalsIgnoreCase(action)) {
|
||||
mobileApp.setType(mobileAppType);
|
||||
mobileApp.setLocation(application.getApplicationReleases().get(0).getInstallerPath());
|
||||
return MDMAndroidOperationUtil.createInstallAppOperation(mobileApp);
|
||||
} else if (SubAction.UNINSTALL.toString().equalsIgnoreCase(action)) {
|
||||
return MDMAndroidOperationUtil.createAppUninstallOperation(mobileApp);
|
||||
|
||||
@ -26,7 +26,8 @@
|
||||
"react-router-dom": "latest",
|
||||
"react-scripts": "2.1.8",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"storm-react-diagrams": "^5.2.1"
|
||||
"storm-react-diagrams": "^5.2.1",
|
||||
"react-star-ratings": "^2.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.0",
|
||||
|
||||
@ -9,10 +9,19 @@
|
||||
"invokerUri": "/api/application-mgt-handler/v1.0/invoke",
|
||||
"loginUri": "/api/application-mgt-handler/v1.0/login"
|
||||
},
|
||||
"serverUrl" : "https://localhost:9443",
|
||||
"serverUrl": "https://localhost:9443",
|
||||
"defaultPlatformIcons": {
|
||||
"default": "http://www.newdesignfile.com/postpic/2015/08/square-app-icon-blue_77131.png",
|
||||
"android": "data:image/png;base64,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",
|
||||
"ios" : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOEAAADhCAMAAAAJbSJIAAAAQlBMVEWpqan///+mpqaqqqr39/f7+/vc3Nz29vatra28vLyysrLz8/Pr6+u/v7+4uLjh4eHX19fIyMju7u7R0dHNzc3Z2dlmxcmlAAAJOUlEQVR4nO2dB7bjMAhFFbn3mv1vdeyUmfzECJAVg/+ZtwBFN6ogwOaiU0lVp32XBGjJBGgjsJKsvg6lXZTXAZpTR5h1UxFZa1ZFv5Bw7Jv8gfcrCcepjf7i/ULCcf7J99sIkyk37/pVO03X2g9AU44BWtZBOA5mA9C0v4Uw2RxAY2xRBWhdAeGyAjcBjR3iAM3LE1bDJt5KOP2KW1vdQIDG9CF+QJqwbmHAvAvxC8KE9fYec1cb4jgUJqxLB6BtshC/IUroBDRmCvIjkoSVa4ouyzAN8iuChEnjBAxzoxElnJx8xgxhfkaOMP20Jb4xSeUIXQfhfZIG2UnlCJPBvQiNmQP9khQhNkdNFGafESMcC2QIbRPqp2QIkwmbozbIjW2VDOGIzdFwQyhEOGNDaIINoQxhFWFDOISwfe8SIURPiiBOtockCGN0jgYx7h+SIEQ30iaEj+0pAcIEu6+VQbwXTwkQdshREQVxsf2VACHoPXzO0UBX7oeOJ6zck9TmIRfhRYIQuXMHeVF71fGEsxMwjI/0VYcTZi7vjA27jd50OKHLtrdlIM/Fqw4ndJwVC2DQc+KuwwmvMGAYL/67DifsoWVoA/lH33U0YQKZhgFt3p86nBCwnL6xx9x1NGG8SZgP35mhq44mzD4JrSm+sYc+dTRh9XHg2/b6vQG8iBNa2/Zf5RMgfHEFWxs1XWBL4lNHE46PV9E1QLbtqy+uv6cOJyzyPC/LopmChDgTdLxtUVVVfBDcTdLxNN9XSMJk0f5W4rHu0utNadfVdbUzuC0EYTx2136ah1XzPF272neDzLp+btoyf1hY0bJi26IZprT2x9xLmNRTU5RlHt1vJ7du5WXbTDV7OKvrsMB9BJpau5IWQ+r5t+0iTLrhwbZx1SwHjkciThuopYeisrn6LAJ/wqRuIuvyzy8H+kAbybgrjLOpZ4O24U8NX8IsLUh9Wi5lSJ/iei4JTT0bLDqmw9iPsCLx3fuUD46bWVJfm80Qb7i9xRJhrUgfwmXNcHplo2La3gvHbqAP3wtjw7kPeRDWDRCX7ehT2fTvKyjr5oLb0LO9fKA7rdiEyeQOmYQ6Fa2Q/1pZ8Ere9PyptqcOI5dw2UC9exXl7dxVcTamyyHjD/dobCCuRiZh6jmvnlqP7+WM2dfIo6mSNlNZhBkeJXKkLOm5n0P46WMRlp0I11UGYY3FoglowI9/OqEzcUBKhP2GTNhhERQyitBRpBKiIb1impGDkUiIZEZIyiJpGTTCUS8gemiQCJHUD2m5o20phFjqh7Tcb6sUQjTSTlyueUogRMPqpWWdhyJOWJfSBIiQZFqU0Bnho0AWi6JCCXtpBEQF9vyIESqfo/vvpduBBXpEMPQRwlQ1oJ1324ex6ssMLSvDTQiGaGkQsaiEm9Dfr/Z9WYJ9jxLqcjy9iRrw7iLMNJ8U6DlIIbwqnqT0WFQHYVJIY8BiJHo7CLHcFkkx0qBhwgTLbRFUywhcgAlHvZPUciIEYEK9hq9l1ZMACfGSAGIqw7xyj2pdwLQnJ5ywU3sYtrzQIYgQrwkgJmaSMESo1j3DTjyBCNGqB1Ky3JonEGGndAgN8fUeJdR7VrCrLUCECl+0b8rZxQgAwkzrMuTXkwAIa6VDaPgZbgChWi8ivw4fQKh1o/HIZQcI1W40/DhogFDpRmMLNiBAmEijAOJZhk5CpZPUXkMRVloJPfLZtwlHrYQeWSXbhFoPfOuRUnIyQj4gQKjVdop+PWH+n5BMqPXi/Z/wP6F+Qp88tHMRhjsP1RJ6lOM7GaFHlZBznYesp9FzEnqUbj0ZYTAbX61tEcxPo5UwnK9NqxcjnL8Ur9YspVA+b62+toDvFko9wuwwBZhQbdwl/9ssAKHWOAWP7+sAhHqjg9k1QM/2fmgirmP/bG/AxnKL7gOE6Bco5MSthw3FYqjdTNnf7oQI9W6mJuINIuTb0buZLgYG6/p9uqgvw7WDIcJa71bDdEhBhMg3GmTFqowNEepOreTMU9CLrDoxjxODecI475vIiV0wofIUZ0p1IYRQXVGoN0VYXRqUUH01DOpuAxNqTl27iYgIE+qtm/QULQbsnNl5T1GK0jpeVSfd58WqnFCSzpVDqvy8WJXvqouRqV+Iq1Cnhuvt/wQL0eBeDReh8ovbU0h5DBdhfIKFuMq2nWPDcUaoqLagXuQsHO4k1OzK+ClbTpCx4Y4yku44Q1EBvNm4CZXbFz9kAS+jm/A809SAwTZuQsWu708BIdJItJ92I/FFUKwNQqg24flTUEQYQqg3H/hdFqp3gsWknuTm5rD4McJKaybiu8AEYTSu+CR7DXz9Rgm1+00fgm0olPAM7pr1rQZ0EOPR72dwZpgIDiTCCZNGuvsEFbAvg5DBoN41vAyhI2SRQKi5Mt1DrkApShaKfgvDVbOGlGejfa9xFv8iESofRPfXEUiEaqvV3BXtq1h+H0TN92/kAxc0QtVGVOt+76Z+o0TvmWiRuGgiIfhZe3E5bqQsQr0mBhpuSs47VfpeatGQDDJhpfPuhldMpucOq7yAE8q3MbKjNZrChLLlDMJK3yBSoto5Ge7qkjBIKaWsHH5t11P3hdSHsNJ1KNIyu3l1GFJpqFcR0555hLGi/dQSUxGZtTQUfciSmonIrRaip1I7NTmIS6jFBU4vCc2u+JLpmKf0bFl+TRsdxjC95rVH1R4NR0ZBz9DzqUsk77TJGaUVfAjFK9Kzinz6EEqfioG+4OGU6Jsi6nsKQXjp5bw23I8jeBJeZjFC7qcDfAnF7jYltxiWL6FUtnfOrpXsTXiJJRAjfrEvf0Lf/D17lxdguGpmRETm5WbBysu2LW5qyzzigrKrfuwlXBAZdLYc0nqssviurBrrbioMHdI6gma+RXhJJmrniuu2zyHpmpwGadm76F37CBdDg3C7ydvedQtJ0iYnXCAaj6qQq/YSXsbGuIbA5u2MH9HjVOTOgbQlIQ9vW7sJL/EE5rhZUw7A7HxXlQ4t+FfZvPEoqP/QfsLF1JjLjb7ZpV8TnKzzoaTut5ekjZrUdwAvYQiXzk3lz75ZG7VTx62tVn1ArlvwzG7nh4IQLoxVuvbtqbzp68yjyv8y58fbdH220y54Xu38UyDCVVl9nVb13bhjUi1KsuWoTNOuruKddKv+ANf/kjfiNBjwAAAAAElFTkSuQmCC"
|
||||
"default": {
|
||||
"icon": "mobile",
|
||||
"color": "#535c68"
|
||||
},
|
||||
"android": {
|
||||
"icon": "android",
|
||||
"color": "#7db343"
|
||||
},
|
||||
"ios": {
|
||||
"icon": "apple",
|
||||
"color": "#535c68"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,72 @@
|
||||
.d-rating .numeric-data{
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
padding: 20px 0 20px 0;
|
||||
vertical-align: top;
|
||||
text-align: center;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
.d-rating .bar-containers{
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
padding: 20px 20px 20px 30px;
|
||||
vertical-align: top;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.d-rating .bar-containers .bar-container{
|
||||
color: #737373;
|
||||
font-weight: 400;
|
||||
height: 20px;
|
||||
margin-bottom: 4px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.d-rating .bar-containers .bar-container .number{
|
||||
font-size: 11px;
|
||||
left: -16px;
|
||||
letter-spacing: 1px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.d-rating .bar-containers .bar-container .bar{
|
||||
transition: width .25s ease;
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
opacity: .8;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.bar-container .rate-5{
|
||||
background: #57bb8a;
|
||||
}
|
||||
|
||||
.bar-container .rate-4{
|
||||
background: #9ace6a;
|
||||
}
|
||||
|
||||
.bar-container .rate-3{
|
||||
background: #ffcf02;
|
||||
}
|
||||
|
||||
.bar-container .rate-2{
|
||||
background: #ff9f02;
|
||||
}
|
||||
|
||||
.bar-container .rate-1{
|
||||
background: #ff6f31;
|
||||
}
|
||||
|
||||
.d-rating .numeric-data .rate{
|
||||
color: #333;
|
||||
font-size: 64px;
|
||||
font-weight: 100;
|
||||
line-height: 64px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.d-rating .numeric-data .people-count{
|
||||
padding-top: 6px;
|
||||
}
|
||||
@ -0,0 +1,122 @@
|
||||
import React from "react";
|
||||
import {Row, Typography, Icon} from "antd";
|
||||
import StarRatings from "react-star-ratings";
|
||||
import "./DetailedRating.css";
|
||||
import config from "../../../../public/conf/config.json";
|
||||
import axios from "axios";
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
|
||||
class DetailedRating extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
detailedRating: null
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getData(this.props.uuid);
|
||||
}
|
||||
|
||||
componentDidUpdate(nextProps) {
|
||||
if (nextProps !== this.props) {
|
||||
this.getData(this.props.uuid);
|
||||
}
|
||||
}
|
||||
|
||||
getData = (uuid)=>{
|
||||
const request = "method=get&content-type=application/json&payload={}&api-endpoint=/application-mgt-store/v1.0/reviews/"+uuid+"/rating";
|
||||
|
||||
return axios.post('https://' + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invokerUri, request
|
||||
).then(res => {
|
||||
if (res.status === 200) {
|
||||
let detailedRating = res.data.data;
|
||||
this.setState({
|
||||
detailedRating
|
||||
})
|
||||
}
|
||||
|
||||
}).catch(function (error) {
|
||||
if (error.response.status === 401) {
|
||||
window.location.href = 'https://localhost:9443/store/login';
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const detailedRating = this.state.detailedRating;
|
||||
|
||||
console.log(detailedRating);
|
||||
|
||||
if(detailedRating ==null){
|
||||
return null;
|
||||
}
|
||||
|
||||
const totalCount = detailedRating.noOfUsers;
|
||||
const ratingVariety = detailedRating.ratingVariety;
|
||||
|
||||
const ratingArray = [];
|
||||
|
||||
for (let [key, value] of Object.entries(ratingVariety)) {
|
||||
ratingArray.push(value);
|
||||
}
|
||||
|
||||
const maximumRating = Math.max(...ratingArray);
|
||||
|
||||
const ratingBarPercentages = [0,0,0,0,0];
|
||||
|
||||
if(maximumRating>0){
|
||||
for(let i = 0; i<5; i++){
|
||||
ratingBarPercentages[i] = (ratingVariety[(i+1).toString()])/maximumRating*100;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(ratingBarPercentages);
|
||||
|
||||
return (
|
||||
<Row className="d-rating">
|
||||
<div className="numeric-data">
|
||||
<div className="rate">{detailedRating.ratingValue.toFixed(1)}</div>
|
||||
<StarRatings
|
||||
rating={detailedRating.ratingValue}
|
||||
starRatedColor="#777"
|
||||
starDimension = "16px"
|
||||
starSpacing = "2px"
|
||||
numberOfStars={5}
|
||||
name='rating'
|
||||
/>
|
||||
<br/>
|
||||
<Text type="secondary" className="people-count"><Icon type="team" /> {totalCount} total</Text>
|
||||
</div>
|
||||
<div className="bar-containers">
|
||||
<div className="bar-container">
|
||||
<span className="number">5</span>
|
||||
<span className="bar rate-5" style={{width: ratingBarPercentages[4]+"%"}}> </span>
|
||||
</div>
|
||||
<div className="bar-container">
|
||||
<span className="number">4</span>
|
||||
<span className="bar rate-4" style={{width: ratingBarPercentages[3]+"%"}}> </span>
|
||||
</div>
|
||||
<div className="bar-container">
|
||||
<span className="number">3</span>
|
||||
<span className="bar rate-3" style={{width: ratingBarPercentages[2]+"%"}}> </span>
|
||||
</div>
|
||||
<div className="bar-container">
|
||||
<span className="number">2</span>
|
||||
<span className="bar rate-2" style={{width: ratingBarPercentages[1]+"%"}}> </span>
|
||||
</div>
|
||||
<div className="bar-container">
|
||||
<span className="number">1</span>
|
||||
<span className="bar rate-1" style={{width: ratingBarPercentages[0]+"%"}}> </span>
|
||||
</div>
|
||||
</div>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default DetailedRating;
|
||||
@ -0,0 +1,95 @@
|
||||
import React from 'react';
|
||||
import {Drawer, Row, Col, Typography, Divider, Tag, Avatar, List} from 'antd';
|
||||
import "../../../App.css";
|
||||
import DetailedRating from "../detailed-rating/DetailedRating";
|
||||
|
||||
const {Text, Title, Paragraph} = Typography;
|
||||
|
||||
class AppDetailsDrawer extends React.Component {
|
||||
|
||||
render() {
|
||||
const {app, visible, onClose} = this.props;
|
||||
if (app == null) {
|
||||
return null;
|
||||
}
|
||||
console.log(app);
|
||||
return (
|
||||
<div>
|
||||
|
||||
<Drawer
|
||||
placement="right"
|
||||
width={640}
|
||||
closable={false}
|
||||
onClose={onClose}
|
||||
visible={visible}
|
||||
>
|
||||
<div style={{textAlign: "center"}}>
|
||||
<img
|
||||
style={{
|
||||
marginBottom: 10,
|
||||
width: 100,
|
||||
borderRadius: "28%",
|
||||
border: "1px solid #ddd"
|
||||
}}
|
||||
src={app.applicationReleases[0].iconPath}
|
||||
/>
|
||||
<Title level={2}>{app.name}</Title>
|
||||
</div>
|
||||
<Divider/>
|
||||
<Paragraph type="secondary" ellipsis={{rows: 3, expandable: true}}>{app.description}</Paragraph>
|
||||
<Divider dashed={true}/>
|
||||
<Text strong={true}>Categories</Text>
|
||||
<br/>
|
||||
<br/>
|
||||
<span>
|
||||
{app.appCategories.map(category => {
|
||||
return (
|
||||
<Tag color="blue" key={category} style={{paddingBottom: 5}}>
|
||||
{category}
|
||||
</Tag>
|
||||
);
|
||||
})}
|
||||
</span>
|
||||
|
||||
<Divider dashed={true}/>
|
||||
<Text strong={true}>Tags</Text>
|
||||
<br/>
|
||||
<br/>
|
||||
<span>
|
||||
{app.tags.map(category => {
|
||||
return (
|
||||
<Tag color="gold" key={category} style={{paddingBottom: 5}}>
|
||||
{category}
|
||||
</Tag>
|
||||
);
|
||||
})}
|
||||
</span>
|
||||
<Divider dashed={true}/>
|
||||
<Text strong={true}>Releases</Text>
|
||||
<br/>
|
||||
<List
|
||||
itemLayout="horizontal"
|
||||
dataSource={app.applicationReleases}
|
||||
renderItem={release => (
|
||||
<List.Item>
|
||||
<List.Item.Meta
|
||||
title={<a href={"apps/releases/"+release.uuid}>{release.version}</a>}
|
||||
description={
|
||||
<div>
|
||||
Status : <Tag>{release.currentStatus}</Tag> Release Type <Tag color="green">{release.releaseType}</Tag>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
<Divider dashed={true}/>
|
||||
|
||||
<DetailedRating uuid={app.applicationReleases[0].uuid}/>
|
||||
</Drawer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default AppDetailsDrawer;
|
||||
@ -0,0 +1,180 @@
|
||||
import React from "react";
|
||||
import {Avatar, Card, Col, Row, Table, Typography, Tag, Icon, message} from "antd";
|
||||
import {connect} from "react-redux";
|
||||
import {getApps} from "../../../js/actions";
|
||||
import axios from "axios";
|
||||
import config from "../../../../public/conf/config.json";
|
||||
|
||||
const {Title} = Typography;
|
||||
|
||||
// connecting state.apps with the component
|
||||
const mapStateToProps = state => {
|
||||
return {apps: state.apps}
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '',
|
||||
dataIndex: 'name',
|
||||
render: (name, row) => {
|
||||
return (
|
||||
<div>
|
||||
<Avatar shape="square" size="large"
|
||||
style={{
|
||||
marginRight: 20,
|
||||
borderRadius: "28%",
|
||||
border: "1px solid #ddd"
|
||||
}}
|
||||
src={row.applicationReleases[0].iconPath}
|
||||
/>
|
||||
{name}
|
||||
</div>);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Categories',
|
||||
dataIndex: 'appCategories',
|
||||
render: appCategories => (
|
||||
<span>
|
||||
{appCategories.map(category => {
|
||||
return (
|
||||
<Tag color="blue" key={category}>
|
||||
{category}
|
||||
</Tag>
|
||||
);
|
||||
})}
|
||||
</span>
|
||||
)
|
||||
},
|
||||
{
|
||||
title: 'Platform',
|
||||
dataIndex: 'deviceType',
|
||||
render: platform => {
|
||||
const defaultPlatformIcons = config.defaultPlatformIcons;
|
||||
let icon = defaultPlatformIcons.default.icon;
|
||||
let color = defaultPlatformIcons.default.color;
|
||||
if (defaultPlatformIcons.hasOwnProperty(platform)) {
|
||||
icon = defaultPlatformIcons[platform].icon;
|
||||
color = defaultPlatformIcons[platform].color;
|
||||
}
|
||||
return (<span style={{fontSize: 20, color: color, textAlign: "center"}}><Icon type={icon}
|
||||
theme="filled"/></span>)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Type',
|
||||
dataIndex: 'type'
|
||||
},
|
||||
{
|
||||
title: 'Subscription',
|
||||
dataIndex: 'subType'
|
||||
},
|
||||
];
|
||||
|
||||
class ConnectedAppsTable extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
pagination: {
|
||||
total: 100
|
||||
},
|
||||
apps: []
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.fetch();
|
||||
}
|
||||
|
||||
handleTableChange = (pagination, filters, sorter) => {
|
||||
const pager = {...this.state.pagination};
|
||||
pager.current = pagination.current;
|
||||
|
||||
this.setState({
|
||||
pagination: pager,
|
||||
});
|
||||
this.fetch({
|
||||
results: pagination.pageSize,
|
||||
page: pagination.current,
|
||||
sortField: sorter.field,
|
||||
sortOrder: sorter.order,
|
||||
...filters,
|
||||
});
|
||||
};
|
||||
|
||||
fetch = (params = {}) => {
|
||||
this.setState({loading: true});
|
||||
|
||||
const extraParams = {
|
||||
offset: 10 * (params.page - 1),
|
||||
limit: 10
|
||||
};
|
||||
// note: encode with '%26' not '&'
|
||||
const encodedExtraParams = Object.keys(extraParams).map(key => key + '=' + extraParams[key]).join('%26');
|
||||
const parameters = {
|
||||
method: "post",
|
||||
'content-type': "application/json",
|
||||
payload: JSON.stringify({}),
|
||||
'api-endpoint': "/application-mgt-publisher/v1.0/applications?" + encodedExtraParams
|
||||
};
|
||||
|
||||
const request = Object.keys(parameters).map(key => key + '=' + parameters[key]).join('&');
|
||||
console.log(request);
|
||||
axios.post('https://' + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invokerUri, request
|
||||
).then(res => {
|
||||
if (res.status === 200) {
|
||||
let apps = [];
|
||||
|
||||
if (res.data.data.hasOwnProperty("applications")) {
|
||||
apps = res.data.data.applications;
|
||||
}
|
||||
const pagination = {...this.state.pagination};
|
||||
// Read total count from server
|
||||
// pagination.total = data.totalCount;
|
||||
pagination.total = 200;
|
||||
this.setState({
|
||||
loading: false,
|
||||
apps: apps,
|
||||
pagination,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
if (error.response.status === 401) {
|
||||
message.error('You are not logged in');
|
||||
window.location.href = 'https://localhost:9443/publisher/login';
|
||||
} else {
|
||||
message.error('Something went wrong... :(');
|
||||
}
|
||||
|
||||
this.setState({loading: false});
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
console.log("rendered");
|
||||
return (
|
||||
|
||||
<Table
|
||||
rowKey={record => record.id}
|
||||
dataSource={this.state.apps}
|
||||
columns={columns}
|
||||
pagination={this.state.pagination}
|
||||
onChange={this.handleTableChange}
|
||||
onRow={(record, rowIndex) => {
|
||||
return {
|
||||
onClick: event => {
|
||||
this.props.showDrawer(record);
|
||||
},
|
||||
};
|
||||
}}
|
||||
/>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const AppsTable = connect(mapStateToProps, {getApps})(ConnectedAppsTable);
|
||||
|
||||
export default AppsTable;
|
||||
@ -0,0 +1,74 @@
|
||||
import React from "react";
|
||||
import {Avatar, Card, Col, Row, Table, Typography, Input, Divider, Checkbox, Select, Button} from "antd";
|
||||
|
||||
const {Option} = Select;
|
||||
const {Title, Text} = Typography;
|
||||
|
||||
class Filters extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
||||
<Card>
|
||||
<Row>
|
||||
<Col span={6}>
|
||||
<Title level={4}>Filter</Title>
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider/>
|
||||
|
||||
<Text strong={true}>Category</Text>
|
||||
<br/><br/>
|
||||
<Select
|
||||
mode="multiple"
|
||||
style={{width: '100%'}}
|
||||
placeholder="All Categories"
|
||||
>
|
||||
<Option key={1}>IoT</Option>
|
||||
<Option key={2}>EMM</Option>
|
||||
</Select>
|
||||
<Divider/>
|
||||
|
||||
<Text strong={true}>Platform</Text>
|
||||
<br/><br/>
|
||||
<Checkbox>Android</Checkbox><br/>
|
||||
<Checkbox>iOS</Checkbox><br/>
|
||||
<Checkbox>Windows</Checkbox><br/>
|
||||
<Checkbox>Default</Checkbox><br/>
|
||||
<Divider/>
|
||||
|
||||
<Text strong={true}>Tags</Text>
|
||||
<br/><br/>
|
||||
<Select
|
||||
mode="multiple"
|
||||
style={{width: '100%'}}
|
||||
placeholder="All Tags"
|
||||
>
|
||||
<Option key={1}>test tag</Option>
|
||||
</Select>
|
||||
|
||||
<Divider/>
|
||||
<Text strong={true}>Type</Text>
|
||||
<br/><br/>
|
||||
<Checkbox>Enterprise</Checkbox><br/>
|
||||
<Checkbox>Public</Checkbox><br/>
|
||||
<Checkbox>Web APP</Checkbox><br/>
|
||||
<Checkbox>Web Clip</Checkbox><br/>
|
||||
<Divider/>
|
||||
|
||||
<Text strong={true}>Subscription</Text>
|
||||
<br/><br/>
|
||||
<Checkbox>Free</Checkbox><br/>
|
||||
<Checkbox>Paid</Checkbox><br/>
|
||||
<Divider/>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default Filters;
|
||||
@ -0,0 +1,76 @@
|
||||
import React from "react";
|
||||
import {Avatar, Card, Col, Row, Table, Typography, Input, Divider, Checkbox, Select, Button} from "antd";
|
||||
import {connect} from "react-redux";
|
||||
import {getApps} from "../../../js/actions";
|
||||
import AppsTable from "./AppsTable";
|
||||
import Filters from "./Filters";
|
||||
import AppDetailsDrawer from "./AppDetailsDrawer";
|
||||
|
||||
const {Option} = Select;
|
||||
const {Title, Text} = Typography;
|
||||
const Search = Input.Search;
|
||||
// connecting state.apps with the component
|
||||
const mapStateToProps = state => {
|
||||
return {apps: state.apps}
|
||||
};
|
||||
|
||||
|
||||
class ConnectedListApps extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isDrawerVisible: false,
|
||||
selectedApp: null
|
||||
}
|
||||
}
|
||||
|
||||
//handler to show app drawer
|
||||
showDrawer = (app) => {
|
||||
console.log(app);
|
||||
this.setState({
|
||||
isDrawerVisible: true,
|
||||
selectedApp: app
|
||||
});
|
||||
};
|
||||
|
||||
// handler to close the app drawer
|
||||
closeDrawer = () => {
|
||||
this.setState({
|
||||
isDrawerVisible: false
|
||||
})
|
||||
};
|
||||
|
||||
render() {
|
||||
const {isDrawerVisible} = this.state;
|
||||
return (
|
||||
<Row gutter={28}>
|
||||
<Col md={6}>
|
||||
<Filters/>
|
||||
</Col>
|
||||
<Col md={18}>
|
||||
<Card>
|
||||
<Row>
|
||||
<Col span={6}>
|
||||
<Title level={4}>Apps</Title>
|
||||
</Col>
|
||||
<Col span={18} style={{textAlign: "right"}}>
|
||||
<Search
|
||||
placeholder="input search text"
|
||||
onSearch={value => console.log(value)}
|
||||
style={{width: 200}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider dashed={true}/>
|
||||
<AppsTable showDrawer={this.showDrawer} />
|
||||
<AppDetailsDrawer visible={isDrawerVisible} onClose={this.closeDrawer} app={this.state.selectedApp}/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const ListApps = connect(mapStateToProps, {getApps})(ConnectedListApps);
|
||||
|
||||
export default ListApps;
|
||||
@ -28,7 +28,7 @@ class Dashboard extends React.Component {
|
||||
<Menu
|
||||
theme="light"
|
||||
mode="horizontal"
|
||||
defaultSelectedKeys={['2']}
|
||||
defaultSelectedKeys={['1']}
|
||||
style={{lineHeight: '64px'}}
|
||||
>
|
||||
<Menu.Item key="1"><Link to="/publisher/apps"><Icon type="appstore"/>Apps</Link></Menu.Item>
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
import React from "react";
|
||||
import "antd/dist/antd.css";
|
||||
import {PageHeader, Typography,Input, Button, Row, Col} from "antd";
|
||||
import AppList from "../../../components/apps/AppList";
|
||||
import ReleaseModal from "../../../components/apps/ReleaseModal";
|
||||
|
||||
const Search = Input.Search;
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: 'index',
|
||||
breadcrumbName: 'Publisher',
|
||||
},
|
||||
{
|
||||
path: 'first',
|
||||
breadcrumbName: 'Dashboard',
|
||||
},
|
||||
{
|
||||
path: 'second',
|
||||
breadcrumbName: 'Apps',
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
class Apps extends React.Component {
|
||||
routes;
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.routes = props.routes;
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<PageHeader
|
||||
breadcrumb={{routes}}
|
||||
/>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 780}}>
|
||||
<Row style={{padding:10}}>
|
||||
<Col span={6} offset={18}>
|
||||
<Search
|
||||
placeholder="search"
|
||||
onSearch={value => console.log(value)}
|
||||
style={{ width: 200}}
|
||||
/>
|
||||
<Button style={{margin:5}}>Advanced Search</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<ReleaseModal/>
|
||||
<AppList/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Apps;
|
||||
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import "antd/dist/antd.css";
|
||||
import {PageHeader, Typography,Input, Button, Row, Col} from "antd";
|
||||
import AppList from "../../../components/apps/AppList";
|
||||
import ListApps from "../../../components/apps/list-apps/ListApps";
|
||||
import ReleaseModal from "../../../components/apps/ReleaseModal";
|
||||
|
||||
const Search = Input.Search;
|
||||
@ -37,18 +37,8 @@ class Apps extends React.Component {
|
||||
breadcrumb={{routes}}
|
||||
/>
|
||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 780}}>
|
||||
<Row style={{padding:10}}>
|
||||
<Col span={6} offset={18}>
|
||||
<Search
|
||||
placeholder="search"
|
||||
onSearch={value => console.log(value)}
|
||||
style={{ width: 200}}
|
||||
/>
|
||||
<Button style={{margin:5}}>Advanced Search</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<ReleaseModal/>
|
||||
<AppList/>
|
||||
<ListApps/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@ -68,7 +68,7 @@ class AddReview extends React.Component {
|
||||
});
|
||||
|
||||
setTimeout(()=>{
|
||||
window.location.reload();
|
||||
window.location.href= uuid;
|
||||
},2000)
|
||||
}else{
|
||||
this.setState({
|
||||
|
||||
@ -51,7 +51,8 @@
|
||||
javax.xml.bind.annotation; version="${javax.xml.bind.imp.pkg.version}",
|
||||
com.fasterxml.jackson.annotation;version="${jackson-annotations.version}",
|
||||
org.wso2.carbon.analytics.datasource.commons;version="${carbon.analytics.version.range}",
|
||||
io.swagger.annotations; version="${swagger.annotations.version}"; resolution:=optional
|
||||
io.swagger.annotations; version="${swagger.annotations.version}"; resolution:=optional,
|
||||
com.google.gson
|
||||
</Import-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
@ -103,6 +104,10 @@
|
||||
<groupId>org.wso2.carbon.analytics</groupId>
|
||||
<artifactId>org.wso2.carbon.analytics.datasource.commons</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@ -48,8 +48,7 @@ public class MDMAndroidOperationUtil {
|
||||
|
||||
switch (application.getType()) {
|
||||
case ENTERPRISE:
|
||||
EnterpriseApplication enterpriseApplication =
|
||||
new EnterpriseApplication();
|
||||
EnterpriseApplication enterpriseApplication = new EnterpriseApplication();
|
||||
enterpriseApplication.setType(application.getType().toString());
|
||||
enterpriseApplication.setUrl(application.getLocation());
|
||||
operation.setPayLoad(enterpriseApplication.toJSON());
|
||||
|
||||
Loading…
Reference in New Issue
Block a user