Merge branch 'application-mgt-new' into 'application-mgt-new'

Fix app install functionality in APPM UI

See merge request entgra/carbon-device-mgt!156
feature/appm-store/pbac
Dharmakeerthi Lasantha 6 years ago
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…
Cancel
Save