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' into 'application-mgt-new'
Fix app install functionality in APPM UI See merge request entgra/carbon-device-mgt!156
This commit is contained in:
commit
f3b5a37447
@ -1,56 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import LifeCycleGraph from "./LifeCycleGraph";
|
|
||||||
import {connect} from "react-redux";
|
|
||||||
import {getLifecycle, openLifecycleModal} from "../../../js/actions";
|
|
||||||
import {Button} from "antd";
|
|
||||||
import LifecycleModal from "./LifecycleModal";
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
|
||||||
getLifecycle: () => dispatch(getLifecycle()),
|
|
||||||
openLifecycleModal: (nextState) => dispatch(openLifecycleModal(nextState))
|
|
||||||
});
|
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
|
||||||
return {
|
|
||||||
lifecycle: state.lifecycle,
|
|
||||||
currentStatus : state.release.currentStatus.toUpperCase(),
|
|
||||||
uuid : state.release.uuid
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
class ConnectedLifeCycle extends React.Component {
|
|
||||||
|
|
||||||
constructor(props){
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.openModal = this.openModal.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.props.getLifecycle();
|
|
||||||
}
|
|
||||||
|
|
||||||
openModal() {
|
|
||||||
this.props.openLifecycleModal("IN_REVIEW");
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const lifecycle = this.props.lifecycle;
|
|
||||||
if (lifecycle != null) {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<LifecycleModal uuid={this.props.uuid} currentStatus={this.props.currentStatus}/>
|
|
||||||
<Button onClick={this.openModal}>aaaa</Button>
|
|
||||||
<LifeCycleGraph openModel={this.openModal} currentStatus={this.props.currentStatus} lifecycle={this.props.lifecycle}/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const LifeCycle = connect(mapStateToProps, mapDispatchToProps)(ConnectedLifeCycle);
|
|
||||||
|
|
||||||
export default LifeCycle;
|
|
||||||
@ -1,117 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import {Graph} from 'react-d3-graph';
|
|
||||||
import {connect} from "react-redux";
|
|
||||||
import {getLifecycle, openLifecycleModal} from "../../../js/actions";
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
|
||||||
openLifecycleModal: (nextState) => dispatch(openLifecycleModal(nextState))
|
|
||||||
});
|
|
||||||
|
|
||||||
// the graph configuration, you only need to pass down properties
|
|
||||||
// that you want to override, otherwise default ones will be used
|
|
||||||
const myConfig = {
|
|
||||||
nodeHighlightBehavior: true,
|
|
||||||
directed: true,
|
|
||||||
height: 400,
|
|
||||||
d3: {
|
|
||||||
alphaTarget: 0.05,
|
|
||||||
gravity: -200,
|
|
||||||
linkLength: 200,
|
|
||||||
linkStrength: 1
|
|
||||||
},
|
|
||||||
node: {
|
|
||||||
color: "#d3d3d3",
|
|
||||||
fontColor: "black",
|
|
||||||
fontSize: 12,
|
|
||||||
fontWeight: "normal",
|
|
||||||
highlightFontSize: 12,
|
|
||||||
highlightFontWeight: "bold",
|
|
||||||
highlightStrokeColor: "SAME",
|
|
||||||
highlightStrokeWidth: 1.5,
|
|
||||||
labelProperty: "id",
|
|
||||||
mouseCursor: "pointer",
|
|
||||||
opacity: 1,
|
|
||||||
strokeColor: "none",
|
|
||||||
strokeWidth: 1.5,
|
|
||||||
svg: "",
|
|
||||||
symbolType: "circle",
|
|
||||||
},
|
|
||||||
link: {
|
|
||||||
highlightColor: 'lightblue'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ConnectedLifeCycleGraph extends React.Component {
|
|
||||||
|
|
||||||
|
|
||||||
constructor(props){
|
|
||||||
super(props);
|
|
||||||
this.nextStates = null;
|
|
||||||
this.onClickNode = this.onClickNode.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
onClickNode = function(nodeId) {
|
|
||||||
const nextStates = this.nextStates;
|
|
||||||
if(nextStates.includes(nodeId)){
|
|
||||||
this.props.openLifecycleModal(nodeId);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
// graph payload (with minimalist structure)
|
|
||||||
|
|
||||||
const lifecycle = this.props.lifecycle;
|
|
||||||
const nodes = [];
|
|
||||||
const links = [];
|
|
||||||
this.nextStates = lifecycle[this.props.currentStatus].proceedingStates;
|
|
||||||
|
|
||||||
|
|
||||||
Object.keys(lifecycle).forEach((stateName) => {
|
|
||||||
const state = lifecycle[stateName];
|
|
||||||
let color = "rgb(83, 92, 104)";
|
|
||||||
if (stateName === this.props.currentStatus) {
|
|
||||||
color = "rgb(39, 174, 96)";
|
|
||||||
} else if (this.nextStates.includes(stateName)) {
|
|
||||||
color = "rgb(0,192,255)";
|
|
||||||
}
|
|
||||||
let node = {
|
|
||||||
id: stateName,
|
|
||||||
color: color
|
|
||||||
};
|
|
||||||
nodes.push(node);
|
|
||||||
|
|
||||||
//todo: remove checking property
|
|
||||||
if (state.hasOwnProperty("proceedingStates")) {
|
|
||||||
state.proceedingStates.forEach((proceedingState) => {
|
|
||||||
let link = {
|
|
||||||
source: stateName,
|
|
||||||
target: proceedingState
|
|
||||||
};
|
|
||||||
links.push(link);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
nodes: nodes,
|
|
||||||
links: links
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Graph
|
|
||||||
id="graph-id" // id is mandatory, if no id is defined rd3g will throw an error
|
|
||||||
data={data}
|
|
||||||
config={myConfig}
|
|
||||||
onClickNode={this.onClickNode}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const LifeCycleGraph = connect(null,mapDispatchToProps)(ConnectedLifeCycleGraph);
|
|
||||||
export default LifeCycleGraph;
|
|
||||||
@ -1,111 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import {Modal, Typography, Icon, Input, Form, Checkbox, Button} from 'antd';
|
|
||||||
import {connect} from 'react-redux';
|
|
||||||
import {closeLifecycleModal, updateLifecycleState} from "../../../js/actions";
|
|
||||||
|
|
||||||
const { TextArea } = Input;
|
|
||||||
const { Title } = Typography;
|
|
||||||
|
|
||||||
// connecting state.releaseView with the component
|
|
||||||
const mapStateToProps = state => {
|
|
||||||
return {
|
|
||||||
nextState: state.lifecycleModal.nextState,
|
|
||||||
visible: state.lifecycleModal.visible
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
|
||||||
closeLifecycleModal : () => dispatch(closeLifecycleModal()),
|
|
||||||
updateLifecycleState : (uuid, nextState, reason) => dispatch(updateLifecycleState(uuid, nextState, reason))
|
|
||||||
});
|
|
||||||
|
|
||||||
const Text = Typography;
|
|
||||||
|
|
||||||
class ConnectedLifecycleModal extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
loading: false,
|
|
||||||
visible: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
|
||||||
if (nextProps !== this.props) {
|
|
||||||
this.setState({
|
|
||||||
visible: nextProps.visible,
|
|
||||||
loading: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
showModal = () => {
|
|
||||||
this.setState({
|
|
||||||
visible: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleOk = (e) => {
|
|
||||||
this.setState({
|
|
||||||
visible: false,
|
|
||||||
});
|
|
||||||
this.props.closeLifecycleModal();
|
|
||||||
};
|
|
||||||
|
|
||||||
handleCancel = (e) => {
|
|
||||||
this.setState({
|
|
||||||
visible: false,
|
|
||||||
loading: false
|
|
||||||
});
|
|
||||||
this.props.closeLifecycleModal();
|
|
||||||
};
|
|
||||||
handleSubmit = event => {
|
|
||||||
this.setState({ loading: true });
|
|
||||||
event.preventDefault();
|
|
||||||
this.props.updateLifecycleState(this.props.uuid, this.props.nextState, this.reason.state.value)
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (this.props.nextState != null) {
|
|
||||||
const nextState = this.props.nextState;
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Modal
|
|
||||||
title="Change State"
|
|
||||||
visible={this.state.visible}
|
|
||||||
onCancel={this.handleCancel}
|
|
||||||
footer={null}
|
|
||||||
>
|
|
||||||
<Title level={4}>{this.props.currentStatus} <Icon type="arrow-right" /> {nextState}</Title>
|
|
||||||
<form onSubmit={this.handleSubmit}>
|
|
||||||
<Form.Item>
|
|
||||||
<label htmlFor="username">Reason</label>
|
|
||||||
|
|
||||||
<Input placeholder="Enter the reason" ref={(input) => this.reason = input}/>
|
|
||||||
</Form.Item>
|
|
||||||
{/*<Form.Item>*/}
|
|
||||||
{/*<TextArea*/}
|
|
||||||
{/*placeholder="Please enter the reason..."*/}
|
|
||||||
{/*ref={(input) => this.input = input}*/}
|
|
||||||
{/*autosize*/}
|
|
||||||
{/*/>*/}
|
|
||||||
{/*</Form.Item>*/}
|
|
||||||
<Button key="back" onClick={this.handleCancel}>
|
|
||||||
Cancel
|
|
||||||
</Button>,
|
|
||||||
<Button key="submit" type="primary" htmlType="submit" loading={this.state.loading}>
|
|
||||||
Submit
|
|
||||||
</Button>
|
|
||||||
</form>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const LifecycleModal = connect(mapStateToProps, mapDispatchToProps)(ConnectedLifecycleModal);
|
|
||||||
|
|
||||||
export default LifecycleModal;
|
|
||||||
@ -30,6 +30,7 @@
|
|||||||
"react-router-dom": "latest",
|
"react-router-dom": "latest",
|
||||||
"react-scripts": "2.1.8",
|
"react-scripts": "2.1.8",
|
||||||
"react-star-ratings": "^2.3.0",
|
"react-star-ratings": "^2.3.0",
|
||||||
|
"react-twemoji": "^0.2.3",
|
||||||
"react-virtualized": "^9.21.1",
|
"react-virtualized": "^9.21.1",
|
||||||
"reqwest": "^2.0.5",
|
"reqwest": "^2.0.5",
|
||||||
"storm-react-diagrams": "^5.2.1"
|
"storm-react-diagrams": "^5.2.1"
|
||||||
|
|||||||
@ -12,7 +12,8 @@
|
|||||||
"uri": "/ui-request-handler/invoke",
|
"uri": "/ui-request-handler/invoke",
|
||||||
"publisher": "/application-mgt-publisher/v1.0",
|
"publisher": "/application-mgt-publisher/v1.0",
|
||||||
"store": "/application-mgt-store/v1.0",
|
"store": "/application-mgt-store/v1.0",
|
||||||
"admin" : ""
|
"admin" : "",
|
||||||
|
"deviceMgt" : "/device-mgt/v1.0"
|
||||||
},
|
},
|
||||||
"loginUri": "/ui-request-handler/login",
|
"loginUri": "/ui-request-handler/login",
|
||||||
"platform": "store"
|
"platform": "store"
|
||||||
|
|||||||
@ -22,21 +22,19 @@ class ReleaseView extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
installApp = (type, payload) => {
|
installApp = (type, payload) => {
|
||||||
const {uuid} = this.props.release;
|
const release = this.props.app.applicationReleases[0];
|
||||||
|
const {uuid} = release;
|
||||||
|
|
||||||
const parameters = {
|
|
||||||
method: "post",
|
|
||||||
'content-type': "application/json",
|
|
||||||
payload: JSON.stringify(payload),
|
|
||||||
'api-endpoint': "/application-mgt-store/v1.0/subscription/install/" + uuid + "/" + type + "/install"
|
|
||||||
};
|
|
||||||
|
|
||||||
const request = Object.keys(parameters).map(key => key + '=' + parameters[key]).join('&');
|
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: true,
|
loading: true,
|
||||||
});
|
});
|
||||||
|
const url = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.store + "/subscription/install/" + uuid + "/" + type + "/install";
|
||||||
axios.post(config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.store, request
|
axios.post(
|
||||||
|
url,
|
||||||
|
payload,
|
||||||
|
{
|
||||||
|
headers: {'X-Platform': config.serverConfig.platform}
|
||||||
|
}
|
||||||
).then(res => {
|
).then(res => {
|
||||||
if (res.status === 201) {
|
if (res.status === 201) {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
|||||||
@ -138,7 +138,11 @@ class DeviceInstall extends React.Component {
|
|||||||
const request = Object.keys(parameters).map(key => key + '=' + parameters[key]).join('&');
|
const request = Object.keys(parameters).map(key => key + '=' + parameters[key]).join('&');
|
||||||
|
|
||||||
//send request to the invoker
|
//send request to the invoker
|
||||||
axios.post(config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.store, request
|
axios.get(
|
||||||
|
config.serverConfig.protocol + "://"+config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt+"devices?" + encodedExtraParams,
|
||||||
|
{
|
||||||
|
headers: { 'X-Platform': config.serverConfig.platform }
|
||||||
|
}
|
||||||
).then(res => {
|
).then(res => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const pagination = {...this.state.pagination};
|
const pagination = {...this.state.pagination};
|
||||||
|
|||||||
@ -27,15 +27,11 @@ class GroupInstall extends React.Component {
|
|||||||
const fetchId = this.lastFetchId;
|
const fetchId = this.lastFetchId;
|
||||||
this.setState({data: [], fetching: true});
|
this.setState({data: [], fetching: true});
|
||||||
|
|
||||||
|
axios.post(
|
||||||
const parameters = {
|
config.serverConfig.protocol + "://"+config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt+"/groups?name=" + value,
|
||||||
method: "get",
|
{
|
||||||
'content-type': "application/json",
|
headers: { 'X-Platform': config.serverConfig.platform }
|
||||||
payload: "{}",
|
}
|
||||||
'api-endpoint': "/device-mgt/v1.0/admin/groups?name=" + value
|
|
||||||
};
|
|
||||||
|
|
||||||
axios.post(config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.store, request
|
|
||||||
).then(res => {
|
).then(res => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
if (fetchId !== this.lastFetchId) {
|
if (fetchId !== this.lastFetchId) {
|
||||||
|
|||||||
@ -27,15 +27,11 @@ class RoleInstall extends React.Component {
|
|||||||
const fetchId = this.lastFetchId;
|
const fetchId = this.lastFetchId;
|
||||||
this.setState({data: [], fetching: true});
|
this.setState({data: [], fetching: true});
|
||||||
|
|
||||||
|
axios.get(
|
||||||
const parameters = {
|
config.serverConfig.protocol + "://"+config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt+"/roles?filter=" + value,
|
||||||
method: "get",
|
{
|
||||||
'content-type': "application/json",
|
headers: { 'X-Platform': config.serverConfig.platform }
|
||||||
payload: "{}",
|
}
|
||||||
'api-endpoint': "/device-mgt/v1.0/roles?filter=" + value
|
|
||||||
};
|
|
||||||
|
|
||||||
axios.post(config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.store, request
|
|
||||||
).then(res => {
|
).then(res => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
if (fetchId !== this.lastFetchId) {
|
if (fetchId !== this.lastFetchId) {
|
||||||
|
|||||||
@ -30,7 +30,7 @@ class UserInstall extends React.Component {
|
|||||||
|
|
||||||
//send request to the invoker
|
//send request to the invoker
|
||||||
axios.get(
|
axios.get(
|
||||||
config.serverConfig.protocol + "://"+config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.store+"/device-mgt/v1.0/users/search?username=" + value,
|
config.serverConfig.protocol + "://"+config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt+"/users/search?username=" + value,
|
||||||
{
|
{
|
||||||
headers: { 'X-Platform': config.serverConfig.platform }
|
headers: { 'X-Platform': config.serverConfig.platform }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,4 +13,11 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: -40px;
|
bottom: -40px;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.twemoji {
|
||||||
|
height: 1em;
|
||||||
|
width: 1em;
|
||||||
|
margin: 0 .05em 0 .1em;
|
||||||
|
vertical-align: -0.1em;
|
||||||
}
|
}
|
||||||
@ -1,10 +1,12 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {Avatar} from "antd";
|
import {Avatar} from "antd";
|
||||||
import {List,Typography} from "antd";
|
import {List, Typography} from "antd";
|
||||||
import StarRatings from "react-star-ratings";
|
import StarRatings from "react-star-ratings";
|
||||||
|
import Twemoji from "react-twemoji";
|
||||||
|
import "./Reviews.css";
|
||||||
|
|
||||||
const {Text, Paragraph} = Typography;
|
const {Text, Paragraph} = Typography;
|
||||||
const colorList = ['#f0932b','#badc58','#6ab04c','#eb4d4b','#0abde3', '#9b59b6','#3498db','#22a6b3'];
|
const colorList = ['#f0932b', '#badc58', '#6ab04c', '#eb4d4b', '#0abde3', '#9b59b6', '#3498db', '#22a6b3'];
|
||||||
|
|
||||||
class SingleReview extends React.Component {
|
class SingleReview extends React.Component {
|
||||||
|
|
||||||
@ -17,13 +19,17 @@ class SingleReview extends React.Component {
|
|||||||
<StarRatings
|
<StarRatings
|
||||||
rating={review.rating}
|
rating={review.rating}
|
||||||
starRatedColor="#777"
|
starRatedColor="#777"
|
||||||
starDimension = "12px"
|
starDimension="12px"
|
||||||
starSpacing = "2px"
|
starSpacing="2px"
|
||||||
numberOfStars={5}
|
numberOfStars={5}
|
||||||
name='rating'
|
name='rating'
|
||||||
/>
|
/>
|
||||||
<Text style={{fontSize: 12, color: "#aaa"}} type="secondary"> {review.createdAt}</Text><br/>
|
<Text style={{fontSize: 12, color: "#aaa"}} type="secondary"> {review.createdAt}</Text><br/>
|
||||||
<Paragraph ellipsis={{ rows: 3, expandable: true }} style={{color: "#777"}}>{review.content}</Paragraph>
|
<Twemoji options={{className: 'twemoji'}}>
|
||||||
|
<Paragraph ellipsis={{rows: 3, expandable: true}} style={{color: "#777"}}>
|
||||||
|
{review.content}
|
||||||
|
</Paragraph>
|
||||||
|
</Twemoji>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -31,7 +37,7 @@ class SingleReview extends React.Component {
|
|||||||
<div>
|
<div>
|
||||||
<List.Item.Meta
|
<List.Item.Meta
|
||||||
avatar={
|
avatar={
|
||||||
<Avatar style={{ backgroundColor: randomColor, verticalAlign: 'middle' }} size="large">
|
<Avatar style={{backgroundColor: randomColor, verticalAlign: 'middle'}} size="large">
|
||||||
{avatarLetter}
|
{avatarLetter}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user