forked from community/device-mgt-core
Application mgt new See merge request entgra/carbon-device-mgt!212feature/appm-store/pbac
commit
a4f1bed325
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {Card, Typography, Col, Row} from 'antd';
|
|
||||||
import React from "react";
|
|
||||||
import {Link} from "react-router-dom";
|
|
||||||
import "../../App.css";
|
|
||||||
import StarRatings from 'react-star-ratings';
|
|
||||||
|
|
||||||
const {Meta} = Card;
|
|
||||||
const {Text} = Typography;
|
|
||||||
|
|
||||||
class AppCard extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.handleReleasesClick = this.handleReleasesClick.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleReleasesClick() {
|
|
||||||
this.props.openReleasesModal(this.props.app);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const app = this.props.app;
|
|
||||||
const release = this.props.app.applicationReleases[0];
|
|
||||||
|
|
||||||
const description = (
|
|
||||||
<div className="appCard">
|
|
||||||
<Link to={"/store/"+app.deviceType+"/apps/" + release.uuid}>
|
|
||||||
<Row className="release">
|
|
||||||
<Col span={24} className="release-icon">
|
|
||||||
<img src={release.iconPath} alt="icon"/>
|
|
||||||
{/*<Avatar shape="square" size={128} src={release.iconPath} />*/}
|
|
||||||
</Col>
|
|
||||||
<Col span={24}>
|
|
||||||
<Text strong level={4}>{app.name}</Text><br/>
|
|
||||||
<Text type="secondary" level={4}>{app.deviceType}</Text><br/>
|
|
||||||
<StarRatings
|
|
||||||
rating={app.rating}
|
|
||||||
starRatedColor="#777"
|
|
||||||
starDimension = "12px"
|
|
||||||
starSpacing = "0"
|
|
||||||
numberOfStars={5}
|
|
||||||
name='rating'
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card style={{marginTop: 16}}>
|
|
||||||
<Meta
|
|
||||||
description={description}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AppCard;
|
|
@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 AppCard from "./AppCard";
|
|
||||||
import {Col, message, notification, Row, Result, Skeleton} from "antd";
|
|
||||||
import axios from "axios";
|
|
||||||
import {withConfigContext} from "../../context/ConfigContext";
|
|
||||||
|
|
||||||
class AppList extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
apps: [],
|
|
||||||
loading: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const {deviceType} = this.props;
|
|
||||||
this.props.changeSelectedMenuItem(deviceType);
|
|
||||||
this.fetchData(deviceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState) {
|
|
||||||
if (prevProps.deviceType !== this.props.deviceType) {
|
|
||||||
const {deviceType} = this.props;
|
|
||||||
this.props.changeSelectedMenuItem(deviceType);
|
|
||||||
this.fetchData(deviceType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchData = (deviceType) => {
|
|
||||||
const config = this.props.context;
|
|
||||||
const payload = {};
|
|
||||||
if (deviceType === "web-clip") {
|
|
||||||
payload.appType = "WEB_CLIP";
|
|
||||||
} else {
|
|
||||||
payload.deviceType = deviceType;
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
loading: true
|
|
||||||
});
|
|
||||||
//send request to the invoker
|
|
||||||
axios.post(
|
|
||||||
window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.store + "/applications/",
|
|
||||||
payload,
|
|
||||||
).then(res => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
//todo remove this property check after backend improvement
|
|
||||||
let apps = (res.data.data.hasOwnProperty("applications")) ? res.data.data.applications : [];
|
|
||||||
this.setState({
|
|
||||||
apps: apps,
|
|
||||||
loading: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error.response);
|
|
||||||
if (error.hasOwnProperty("response") && error.response.status === 401) {
|
|
||||||
//todo display a popup with error
|
|
||||||
message.error('You are not logged in');
|
|
||||||
window.location.href = window.location.origin+ '/store/login';
|
|
||||||
} else {
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"Error occurred while trying to load apps.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({loading: false});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {apps,loading} = this.state;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Skeleton loading={loading} active>
|
|
||||||
<Row gutter={16}>
|
|
||||||
{apps.length === 0 && (
|
|
||||||
<Result
|
|
||||||
status="404"
|
|
||||||
title="No apps, yet."
|
|
||||||
subTitle="No apps available, yet! When the administration uploads, apps will show up here."
|
|
||||||
// extra={<Button type="primary">Back Home</Button>}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{apps.map(app => (
|
|
||||||
<Col key={app.id} xs={12} sm={6} md={6} lg={4} xl={3}>
|
|
||||||
<AppCard key={app.id}
|
|
||||||
app={app}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
))}
|
|
||||||
</Row>
|
|
||||||
</Skeleton>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withConfigContext(AppList);
|
|
@ -1,90 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
|
@ -1,140 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {Row, Typography, Icon} from "antd";
|
|
||||||
import StarRatings from "react-star-ratings";
|
|
||||||
import "./DetailedRating.css";
|
|
||||||
import axios from "axios";
|
|
||||||
import {withConfigContext} from "../../../context/ConfigContext";
|
|
||||||
|
|
||||||
const { Text } = Typography;
|
|
||||||
|
|
||||||
|
|
||||||
class DetailedRating extends React.Component{
|
|
||||||
|
|
||||||
constructor(props){
|
|
||||||
super(props);
|
|
||||||
this.state={
|
|
||||||
detailedRating: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const {type,uuid} = this.props;
|
|
||||||
this.getData(type,uuid);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState) {
|
|
||||||
if (prevProps.uuid !== this.props.uuid) {
|
|
||||||
const {type,uuid} = this.props;
|
|
||||||
this.getData(type,uuid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
getData = (type, uuid)=>{
|
|
||||||
const config = this.props.context;
|
|
||||||
|
|
||||||
return axios.get(
|
|
||||||
window.location.origin+ config.serverConfig.invoker.uri +config.serverConfig.invoker.store+"/reviews/"+uuid+"/"+type+"-rating",
|
|
||||||
).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 = window.location.origin+'/store/login';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const detailedRating = this.state.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 withConfigContext(DetailedRating);
|
|
@ -1,171 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {Divider, Row, Col, Typography, Button, Rate, notification} from "antd";
|
|
||||||
import "../../../App.css";
|
|
||||||
import ImgViewer from "../../apps/release/images/ImgViewer";
|
|
||||||
import StarRatings from "react-star-ratings";
|
|
||||||
import DetailedRating from "./DetailedRating";
|
|
||||||
import Reviews from "./review/Reviews";
|
|
||||||
import axios from "axios";
|
|
||||||
import AppInstallModal from "./install/AppInstallModal";
|
|
||||||
import CurrentUsersReview from "./review/CurrentUsersReview";
|
|
||||||
import {withConfigContext} from "../../../context/ConfigContext";
|
|
||||||
|
|
||||||
const {Title, Text, Paragraph} = Typography;
|
|
||||||
|
|
||||||
class ReleaseView extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
loading: false,
|
|
||||||
appInstallModalVisible: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
installApp = (type, payload) => {
|
|
||||||
const config = this.props.context;
|
|
||||||
const release = this.props.app.applicationReleases[0];
|
|
||||||
const {uuid} = release;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
loading: true,
|
|
||||||
});
|
|
||||||
const url = window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.store + "/subscription/" + uuid + "/" + type + "/install";
|
|
||||||
axios.post(
|
|
||||||
url,
|
|
||||||
payload,
|
|
||||||
{
|
|
||||||
headers: {'X-Platform': config.serverConfig.platform}
|
|
||||||
}
|
|
||||||
).then(res => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
appInstallModalVisible: false
|
|
||||||
});
|
|
||||||
notification["success"]({
|
|
||||||
message: 'Done!',
|
|
||||||
description:
|
|
||||||
'App installed triggered.',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
loading: false
|
|
||||||
});
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"Error occurred while installing app",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => {
|
|
||||||
if (error.response.status === 401) {
|
|
||||||
window.location.href = window.location.origin+ '/store/login';
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"Error occurred while installing the app.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
showAppInstallModal = () => {
|
|
||||||
this.setState({
|
|
||||||
appInstallModalVisible: true
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
closeAppInstallModal = () => {
|
|
||||||
this.setState({
|
|
||||||
appInstallModalVisible: false
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {app,deviceType} = this.props;
|
|
||||||
const release = app.applicationReleases[0];
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<AppInstallModal
|
|
||||||
uuid={release.uuid}
|
|
||||||
visible={this.state.appInstallModalVisible}
|
|
||||||
deviceType = {deviceType}
|
|
||||||
onClose={this.closeAppInstallModal}
|
|
||||||
onInstall={this.installApp}/>
|
|
||||||
<div className="release">
|
|
||||||
<Row>
|
|
||||||
<Col xl={4} sm={6} xs={8} className="release-icon">
|
|
||||||
<img src={release.iconPath} alt="icon"/>
|
|
||||||
</Col>
|
|
||||||
<Col xl={10} sm={11} className="release-title">
|
|
||||||
<Title level={2}>{app.name}</Title>
|
|
||||||
<Text>Version : {release.version}</Text><br/><br/>
|
|
||||||
<StarRatings
|
|
||||||
rating={app.rating}
|
|
||||||
starRatedColor="#777"
|
|
||||||
starDimension="20px"
|
|
||||||
starSpacing="2px"
|
|
||||||
numberOfStars={5}
|
|
||||||
name='rating'
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
<Col xl={8} md={10} sm={24} xs={24} style={{float: "right"}}>
|
|
||||||
<div>
|
|
||||||
<Button.Group style={{float: "right"}}>
|
|
||||||
<Button onClick={this.showAppInstallModal} loading={this.state.loading}
|
|
||||||
htmlType="button" type="primary" icon="download">Install</Button>
|
|
||||||
</Button.Group>
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Divider/>
|
|
||||||
<Row>
|
|
||||||
<ImgViewer images={release.screenshots}/>
|
|
||||||
</Row>
|
|
||||||
<Divider/>
|
|
||||||
<Paragraph type="secondary" ellipsis={{rows: 3, expandable: true}}>
|
|
||||||
{release.description}
|
|
||||||
</Paragraph>
|
|
||||||
<Divider/>
|
|
||||||
<CurrentUsersReview uuid={release.uuid}/>
|
|
||||||
<Divider dashed={true}/>
|
|
||||||
<Text>REVIEWS</Text>
|
|
||||||
<Row>
|
|
||||||
<Col lg={18} md={24}>
|
|
||||||
<DetailedRating type="app" uuid={release.uuid}/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
<Reviews type="app" uuid={release.uuid}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withConfigContext(ReleaseView);
|
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 RcViewer from 'rc-viewer';
|
|
||||||
import {Col} from "antd";
|
|
||||||
|
|
||||||
class ImgViewer extends Component {
|
|
||||||
render() {
|
|
||||||
const options = {
|
|
||||||
title: false,
|
|
||||||
toolbar: {
|
|
||||||
zoomIn: 0,
|
|
||||||
zoomOut: 0,
|
|
||||||
oneToOne: 0,
|
|
||||||
reset: 0,
|
|
||||||
prev: 1,
|
|
||||||
play: {
|
|
||||||
show: 0
|
|
||||||
},
|
|
||||||
next: 1,
|
|
||||||
rotateLeft: 0,
|
|
||||||
rotateRight: 0,
|
|
||||||
flipHorizontal: 0,
|
|
||||||
flipVertical: 0
|
|
||||||
},
|
|
||||||
rotatable: false,
|
|
||||||
transition: false,
|
|
||||||
movable : false
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<RcViewer options={options} ref='viewer'>
|
|
||||||
{this.props.images.map((screenshotUrl) => {
|
|
||||||
return (
|
|
||||||
<Col key={"col-" + screenshotUrl} lg={6} md={8} xs={8} className="release-screenshot">
|
|
||||||
<img key={screenshotUrl} src={screenshotUrl}/>
|
|
||||||
</Col>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</RcViewer>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ImgViewer;
|
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {Modal, Tabs} from "antd";
|
|
||||||
import UserInstall from "./UserInstall";
|
|
||||||
import GroupInstall from "./GroupInstall";
|
|
||||||
import RoleInstall from "./RoleInstall";
|
|
||||||
import DeviceInstall from "./DeviceInstall";
|
|
||||||
|
|
||||||
const { TabPane } = Tabs;
|
|
||||||
|
|
||||||
class AppInstallModal extends React.Component{
|
|
||||||
state={
|
|
||||||
data:[]
|
|
||||||
};
|
|
||||||
render() {
|
|
||||||
const {deviceType} = this.props;
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Modal
|
|
||||||
title="Install App"
|
|
||||||
visible={this.props.visible}
|
|
||||||
onCancel={this.props.onClose}
|
|
||||||
footer={null}
|
|
||||||
>
|
|
||||||
<Tabs defaultActiveKey="device">
|
|
||||||
<TabPane tab="Device" key="device">
|
|
||||||
<DeviceInstall deviceType={deviceType} onInstall={this.props.onInstall}/>
|
|
||||||
</TabPane>
|
|
||||||
<TabPane tab="User" key="user">
|
|
||||||
<UserInstall onInstall={this.props.onInstall}/>
|
|
||||||
</TabPane>
|
|
||||||
<TabPane tab="Role" key="role">
|
|
||||||
<RoleInstall onInstall={this.props.onInstall}/>
|
|
||||||
</TabPane>
|
|
||||||
<TabPane tab="Group" key="group">
|
|
||||||
<GroupInstall onInstall={this.props.onInstall}/>
|
|
||||||
</TabPane>
|
|
||||||
</Tabs>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AppInstallModal;
|
|
@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {Typography, Select, Spin, message, notification, Button} from "antd";
|
|
||||||
import debounce from 'lodash.debounce';
|
|
||||||
import axios from "axios";
|
|
||||||
import {withConfigContext} from "../../../../context/ConfigContext";
|
|
||||||
|
|
||||||
const {Text} = Typography;
|
|
||||||
const {Option} = Select;
|
|
||||||
|
|
||||||
|
|
||||||
class GroupInstall extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.lastFetchId = 0;
|
|
||||||
this.fetchUser = debounce(this.fetchUser, 800);
|
|
||||||
}
|
|
||||||
|
|
||||||
state = {
|
|
||||||
data: [],
|
|
||||||
value: [],
|
|
||||||
fetching: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchUser = value => {
|
|
||||||
this.lastFetchId += 1;
|
|
||||||
const fetchId = this.lastFetchId;
|
|
||||||
const config = this.props.context;
|
|
||||||
this.setState({data: [], fetching: true});
|
|
||||||
|
|
||||||
axios.post(
|
|
||||||
window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt+"/groups?name=" + value,
|
|
||||||
|
|
||||||
).then(res => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
if (fetchId !== this.lastFetchId) {
|
|
||||||
// for fetch callback order
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = res.data.data.deviceGroups.map(group => ({
|
|
||||||
text: group.name,
|
|
||||||
value: group.name,
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.setState({data, fetching: false});
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => { console.log(error);
|
|
||||||
if (error.hasOwnProperty("status") && error.response.status === 401) {
|
|
||||||
message.error('You are not logged in');
|
|
||||||
window.location.href = window.location.origin+'/store/login';
|
|
||||||
} else {
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"Error occurred while trying to load groups.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({fetching: false});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChange = value => {
|
|
||||||
this.setState({
|
|
||||||
value,
|
|
||||||
data: [],
|
|
||||||
fetching: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
install = () =>{
|
|
||||||
const {value} = this.state;
|
|
||||||
const data = [];
|
|
||||||
value.map(val=>{
|
|
||||||
data.push(val.key);
|
|
||||||
});
|
|
||||||
this.props.onInstall("group",data);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
|
|
||||||
const {fetching, data, value} = this.state;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Text>Start installing the application for one or more groups by entering the corresponding group name. Select install to automatically start downloading the application for the respective device group/ groups.</Text>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<Select
|
|
||||||
mode="multiple"
|
|
||||||
labelInValue
|
|
||||||
value={value}
|
|
||||||
placeholder="Search groups"
|
|
||||||
notFoundContent={fetching ? <Spin size="small"/> : null}
|
|
||||||
filterOption={false}
|
|
||||||
onSearch={this.fetchUser}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
style={{width: '100%'}}
|
|
||||||
>
|
|
||||||
{data.map(d => (
|
|
||||||
<Option key={d.value}>{d.text}</Option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
<div style={{paddingTop:10, textAlign:"right"}}>
|
|
||||||
<Button disabled={value.length===0} htmlType="button" type="primary" onClick={this.install}>Install</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withConfigContext(GroupInstall);
|
|
@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {Typography, Select, Spin, message, notification, Button} from "antd";
|
|
||||||
import debounce from 'lodash.debounce';
|
|
||||||
import axios from "axios";
|
|
||||||
import {withConfigContext} from "../../../../context/ConfigContext";
|
|
||||||
|
|
||||||
const {Text} = Typography;
|
|
||||||
const {Option} = Select;
|
|
||||||
|
|
||||||
|
|
||||||
class RoleInstall extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.lastFetchId = 0;
|
|
||||||
this.fetchUser = debounce(this.fetchUser, 800);
|
|
||||||
}
|
|
||||||
|
|
||||||
state = {
|
|
||||||
data: [],
|
|
||||||
value: [],
|
|
||||||
fetching: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchUser = value => {
|
|
||||||
const config = this.props.context;
|
|
||||||
this.lastFetchId += 1;
|
|
||||||
const fetchId = this.lastFetchId;
|
|
||||||
this.setState({data: [], fetching: true});
|
|
||||||
|
|
||||||
axios.get(
|
|
||||||
window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt+"/roles?filter=" + value,
|
|
||||||
|
|
||||||
).then(res => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
if (fetchId !== this.lastFetchId) {
|
|
||||||
// for fetch callback order
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = res.data.data.roles.map(role => ({
|
|
||||||
text: role,
|
|
||||||
value: role,
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.setState({data, fetching: false});
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => { console.log(error);
|
|
||||||
if (error.hasOwnProperty("status") && error.response.status === 401) {
|
|
||||||
message.error('You are not logged in');
|
|
||||||
window.location.href = window.location.origin+'/store/login';
|
|
||||||
} else {
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"Error occurred while trying to load roles.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({fetching: false});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChange = value => {
|
|
||||||
this.setState({
|
|
||||||
value,
|
|
||||||
data: [],
|
|
||||||
fetching: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
install = () =>{
|
|
||||||
const {value} = this.state;
|
|
||||||
const data = [];
|
|
||||||
value.map(val=>{
|
|
||||||
data.push(val.key);
|
|
||||||
});
|
|
||||||
this.props.onInstall("role",data);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
|
|
||||||
const {fetching, data, value} = this.state;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Text>Start installing the application for one or more roles by entering the corresponding role name. Select install to automatically start downloading the application for the respective user role/roles.</Text>
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<Select
|
|
||||||
mode="multiple"
|
|
||||||
labelInValue
|
|
||||||
value={value}
|
|
||||||
placeholder="Search roles"
|
|
||||||
notFoundContent={fetching ? <Spin size="small"/> : null}
|
|
||||||
filterOption={false}
|
|
||||||
onSearch={this.fetchUser}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
style={{width: '100%'}}
|
|
||||||
>
|
|
||||||
{data.map(d => (
|
|
||||||
<Option key={d.value}>{d.text}</Option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
<div style={{paddingTop:10, textAlign:"right"}}>
|
|
||||||
<Button disabled={value.length===0} htmlType="button" type="primary" onClick={this.install}>Install</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withConfigContext(RoleInstall);
|
|
@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {Typography, Select, Spin, message, notification, Button} from "antd";
|
|
||||||
import debounce from 'lodash.debounce';
|
|
||||||
import axios from "axios";
|
|
||||||
import {withConfigContext} from "../../../../context/ConfigContext";
|
|
||||||
|
|
||||||
const {Text} = Typography;
|
|
||||||
const {Option} = Select;
|
|
||||||
|
|
||||||
|
|
||||||
class UserInstall extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.lastFetchId = 0;
|
|
||||||
this.fetchUser = debounce(this.fetchUser, 800);
|
|
||||||
}
|
|
||||||
|
|
||||||
state = {
|
|
||||||
data: [],
|
|
||||||
value: [],
|
|
||||||
fetching: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchUser = value => {
|
|
||||||
const config = this.props.context;
|
|
||||||
this.lastFetchId += 1;
|
|
||||||
const fetchId = this.lastFetchId;
|
|
||||||
this.setState({data: [], fetching: true});
|
|
||||||
|
|
||||||
|
|
||||||
//send request to the invoker
|
|
||||||
axios.get(
|
|
||||||
window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt+"/users/search?username=" + value,
|
|
||||||
|
|
||||||
).then(res => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
if (fetchId !== this.lastFetchId) {
|
|
||||||
// for fetch callback order
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = res.data.data.users.map(user => ({
|
|
||||||
text: user.username,
|
|
||||||
value: user.username,
|
|
||||||
}));
|
|
||||||
|
|
||||||
this.setState({data, fetching: false});
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => {
|
|
||||||
if (error.response.hasOwnProperty(status) && error.response.status === 401) {
|
|
||||||
message.error('You are not logged in');
|
|
||||||
window.location.href = window.location.origin+ '/store/login';
|
|
||||||
} else {
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"Error occurred while trying to load users.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({fetching: false});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChange = value => {
|
|
||||||
this.setState({
|
|
||||||
value,
|
|
||||||
data: [],
|
|
||||||
fetching: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
install = () => {
|
|
||||||
const {value} = this.state;
|
|
||||||
const data = [];
|
|
||||||
value.map(val => {
|
|
||||||
data.push(val.key);
|
|
||||||
});
|
|
||||||
this.props.onInstall("user", data);
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {fetching, data, value} = this.state;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Text>Start installing the application for one or more users by entering the corresponding user name. Select install to automatically start downloading the application for the respective user/users. </Text>
|
|
||||||
<p>Select users</p>
|
|
||||||
<Select
|
|
||||||
mode="multiple"
|
|
||||||
labelInValue
|
|
||||||
value={value}
|
|
||||||
placeholder="Enter the username"
|
|
||||||
notFoundContent={fetching ? <Spin size="small"/> : null}
|
|
||||||
filterOption={false}
|
|
||||||
onSearch={this.fetchUser}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
style={{width: '100%'}}
|
|
||||||
>
|
|
||||||
{data.map(d => (
|
|
||||||
<Option key={d.value}>{d.text}</Option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
<div style={{paddingTop: 10, textAlign: "right"}}>
|
|
||||||
<Button disabled={value.length===0} htmlType="button" type="primary" onClick={this.install}>Install</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withConfigContext(UserInstall);
|
|
@ -1,181 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {Drawer, Button, Icon, Row, Col, Typography, Divider, Input, Spin, notification} from 'antd';
|
|
||||||
import StarRatings from "react-star-ratings";
|
|
||||||
import axios from "axios";
|
|
||||||
import {withConfigContext} from "../../../../context/ConfigContext";
|
|
||||||
|
|
||||||
const {Title} = Typography;
|
|
||||||
const {TextArea} = Input;
|
|
||||||
|
|
||||||
class AddReview extends React.Component {
|
|
||||||
state = {
|
|
||||||
visible: false,
|
|
||||||
content: '',
|
|
||||||
rating: 0,
|
|
||||||
loading: false
|
|
||||||
};
|
|
||||||
|
|
||||||
showDrawer = () => {
|
|
||||||
this.setState({
|
|
||||||
visible: true,
|
|
||||||
content: '',
|
|
||||||
rating: 0,
|
|
||||||
loading: false
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onClose = () => {
|
|
||||||
this.setState({
|
|
||||||
visible: false,
|
|
||||||
|
|
||||||
});
|
|
||||||
};
|
|
||||||
changeRating = (newRating, name) => {
|
|
||||||
this.setState({
|
|
||||||
rating: newRating
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onChange = (e) => {
|
|
||||||
this.setState({content: e.target.value})
|
|
||||||
};
|
|
||||||
|
|
||||||
onSubmit = () => {
|
|
||||||
const config = this.props.context;
|
|
||||||
const {content, rating} = this.state;
|
|
||||||
const {uuid} = this.props;
|
|
||||||
this.setState({
|
|
||||||
loading: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
content: content,
|
|
||||||
rating: rating
|
|
||||||
};
|
|
||||||
|
|
||||||
axios.post(
|
|
||||||
window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.store + "/reviews/" + uuid,
|
|
||||||
payload,
|
|
||||||
).then(res => {
|
|
||||||
if (res.status === 201) {
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
notification["success"]({
|
|
||||||
message: 'Done!',
|
|
||||||
description:
|
|
||||||
'Your review has been posted successfully.',
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
window.location.href = uuid;
|
|
||||||
}, 2000)
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"We are unable to add your review right now.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => {
|
|
||||||
if (error.response.status === 401) {
|
|
||||||
window.location.href = window.location.origin+ '/store/login';
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"We are unable to add your review right now.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Button type="primary" onClick={this.showDrawer}>
|
|
||||||
<Icon type="star"/> Add a review
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Drawer
|
|
||||||
// title="Basic Drawer"
|
|
||||||
placement="bottom"
|
|
||||||
closable={false}
|
|
||||||
onClose={this.onClose}
|
|
||||||
visible={this.state.visible}
|
|
||||||
height={400}
|
|
||||||
>
|
|
||||||
<Spin spinning={this.state.loading} tip="Posting your review...">
|
|
||||||
<Row>
|
|
||||||
<Col lg={8}/>
|
|
||||||
<Col lg={8}>
|
|
||||||
<Title level={4}>Add review</Title>
|
|
||||||
<Divider/>
|
|
||||||
<TextArea
|
|
||||||
placeholder="Tell others what you think about this app. Would you recommend it, and why?"
|
|
||||||
onChange={this.onChange}
|
|
||||||
rows={4}
|
|
||||||
value={this.state.content || ''}
|
|
||||||
style={{marginBottom: 20}}
|
|
||||||
/>
|
|
||||||
<StarRatings
|
|
||||||
rating={this.state.rating}
|
|
||||||
changeRating={this.changeRating}
|
|
||||||
starRatedColor="#777"
|
|
||||||
starHoverColor="#444"
|
|
||||||
starDimension="20px"
|
|
||||||
starSpacing="2px"
|
|
||||||
numberOfStars={5}
|
|
||||||
name='rating'
|
|
||||||
/>
|
|
||||||
<br/><br/>
|
|
||||||
<Button onClick={this.onClose} style={{marginRight: 8}}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button disabled={this.state.rating === 0} onClick={this.onSubmit} type="primary">
|
|
||||||
Submit
|
|
||||||
</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Spin>
|
|
||||||
</Drawer>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withConfigContext(AddReview);
|
|
@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {List, message, Typography, Empty, Button, Row, Col, notification} from "antd";
|
|
||||||
import SingleReview from "./singleReview/SingleReview";
|
|
||||||
import axios from "axios";
|
|
||||||
import AddReview from "./AddReview";
|
|
||||||
import {withConfigContext} from "../../../../context/ConfigContext";
|
|
||||||
|
|
||||||
const {Text, Paragraph} = Typography;
|
|
||||||
|
|
||||||
class CurrentUsersReview extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
data: []
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.fetchData();
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchData = () => {
|
|
||||||
const {uuid} = this.props;
|
|
||||||
const config = this.props.context;
|
|
||||||
|
|
||||||
axios.get(
|
|
||||||
window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.store + "/reviews/app/user/" + uuid,
|
|
||||||
).then(res => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
const data = res.data.data.data;
|
|
||||||
this.setState({data});
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => {
|
|
||||||
if (error.response.hasOwnProperty(status) && error.response.status === 401) {
|
|
||||||
message.error('You are not logged in');
|
|
||||||
window.location.href = window.location.origin+ '/store/login';
|
|
||||||
} else {
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"Error occurred while trying to get your review.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
deleteCallback = () =>{
|
|
||||||
this.setState({
|
|
||||||
data: []
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
addCallBack =(review) =>{
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {data} = this.state;
|
|
||||||
const {uuid} = this.props;
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Text>MY REVIEW</Text>
|
|
||||||
<div style={{
|
|
||||||
overflow: "auto",
|
|
||||||
paddingTop: 8,
|
|
||||||
paddingLeft: 24
|
|
||||||
}}>
|
|
||||||
{data.length > 0 && (
|
|
||||||
<div>
|
|
||||||
<List
|
|
||||||
dataSource={data}
|
|
||||||
renderItem={item => (
|
|
||||||
<List.Item key={item.id}>
|
|
||||||
<SingleReview uuid={uuid} review={item} isDeletable={true} isEditable={true} deleteCallback={this.deleteCallback} isPersonalReview={true}/>
|
|
||||||
</List.Item>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
</List>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{data.length === 0 && (
|
|
||||||
<div>
|
|
||||||
<Empty
|
|
||||||
image={Empty.PRESENTED_IMAGE_DEFAULT}
|
|
||||||
imagestyle={{
|
|
||||||
height: 60,
|
|
||||||
}}
|
|
||||||
description={
|
|
||||||
<span>Share your experience with your community by adding a review.</span>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{/*<Button type="primary">Add review</Button>*/}
|
|
||||||
<AddReview uuid={uuid}/>
|
|
||||||
</Empty>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withConfigContext(CurrentUsersReview);
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.infinite-container {
|
|
||||||
overflow: auto;
|
|
||||||
padding: 8px 24px;
|
|
||||||
}
|
|
||||||
.loading-container {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 40px;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading {
|
|
||||||
position: absolute;
|
|
||||||
bottom: -40px;
|
|
||||||
left: 50%;
|
|
||||||
}
|
|
@ -1,155 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {List, message, Avatar, Spin, Button, notification} from 'antd';
|
|
||||||
import "./Reviews.css";
|
|
||||||
|
|
||||||
import InfiniteScroll from 'react-infinite-scroller';
|
|
||||||
import SingleReview from "./singleReview/SingleReview";
|
|
||||||
import axios from "axios";
|
|
||||||
import {withConfigContext} from "../../../../context/ConfigContext";
|
|
||||||
|
|
||||||
const limit = 5;
|
|
||||||
|
|
||||||
class Reviews extends React.Component {
|
|
||||||
state = {
|
|
||||||
data: [],
|
|
||||||
loading: false,
|
|
||||||
hasMore: false,
|
|
||||||
loadMore: false
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.fetchData(0, limit, res => {
|
|
||||||
this.setState({
|
|
||||||
data: res,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchData = (offset, limit, callback) => {
|
|
||||||
|
|
||||||
const {uuid, type} = this.props;
|
|
||||||
const config = this.props.context;
|
|
||||||
|
|
||||||
axios.get(
|
|
||||||
window.location.origin+ config.serverConfig.invoker.uri +config.serverConfig.invoker.store+"/reviews/"+type+"/"+uuid,
|
|
||||||
{
|
|
||||||
headers: {'X-Platform': config.serverConfig.platform}
|
|
||||||
}).then(res => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
let reviews = res.data.data.data;
|
|
||||||
callback(reviews);
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch(function (error) {
|
|
||||||
if (error.response.status === 401) {
|
|
||||||
window.location.href = window.location.origin+ '/store/login';
|
|
||||||
} else {
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"Error occurred while trying to load reviews.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleInfiniteOnLoad = (count) => {
|
|
||||||
const offset = count * limit;
|
|
||||||
let data = this.state.data;
|
|
||||||
this.setState({
|
|
||||||
loading: true,
|
|
||||||
});
|
|
||||||
if (data.length > 149) {
|
|
||||||
this.setState({
|
|
||||||
hasMore: false,
|
|
||||||
loading: false,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.fetchData(offset, limit, res => {
|
|
||||||
if (res.length > 0) {
|
|
||||||
data = data.concat(res);
|
|
||||||
this.setState({
|
|
||||||
data,
|
|
||||||
loading: false,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
hasMore: false,
|
|
||||||
loading: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
enableLoading = () => {
|
|
||||||
this.setState({
|
|
||||||
hasMore: true,
|
|
||||||
loadMore: true
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
deleteCallback = () =>{
|
|
||||||
this.fetchData(0, limit, res => {
|
|
||||||
this.setState({
|
|
||||||
data: res,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {loading, hasMore, data, loadMore} = this.state;
|
|
||||||
const {uuid} = this.props;
|
|
||||||
return (
|
|
||||||
<div className="infinite-container">
|
|
||||||
<InfiniteScroll
|
|
||||||
initialLoad={false}
|
|
||||||
pageStart={0}
|
|
||||||
loadMore={this.handleInfiniteOnLoad}
|
|
||||||
hasMore={!loading && hasMore}
|
|
||||||
useWindow={true}
|
|
||||||
>
|
|
||||||
<List
|
|
||||||
dataSource={data}
|
|
||||||
renderItem={item => (
|
|
||||||
<List.Item key={item.id}>
|
|
||||||
<SingleReview uuid={uuid} review={item} isDeletable={true} isEditable={false} deleteCallback={this.deleteCallback}/>
|
|
||||||
</List.Item>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{loading && hasMore && (
|
|
||||||
<div className="loading-container">
|
|
||||||
<Spin/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</List>
|
|
||||||
</InfiniteScroll>
|
|
||||||
{!loadMore && (data.length >= limit) && (<div style={{textAlign: "center"}}>
|
|
||||||
<Button type="dashed" htmlType="button" onClick={this.enableLoading}>Read All Reviews</Button>
|
|
||||||
</div>)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withConfigContext(Reviews);
|
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
img.twemoji {
|
|
||||||
height: 1em;
|
|
||||||
width: 1em;
|
|
||||||
margin: 0 .05em 0 .1em;
|
|
||||||
vertical-align: -0.1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.edit-button {
|
|
||||||
color: #1890ff;
|
|
||||||
text-decoration: none;
|
|
||||||
outline: none;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 0.8em;
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delete-button {
|
|
||||||
color: #e74c3c;
|
|
||||||
text-decoration: none;
|
|
||||||
outline: none;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 0.8em;
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
@ -1,152 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {Avatar, notification} from "antd";
|
|
||||||
import {List, Typography, Popconfirm} from "antd";
|
|
||||||
import StarRatings from "react-star-ratings";
|
|
||||||
import Twemoji from "react-twemoji";
|
|
||||||
import "./SingleReview.css";
|
|
||||||
import EditReview from "./editReview/EditReview";
|
|
||||||
import axios from "axios";
|
|
||||||
import {withConfigContext} from "../../../../../context/ConfigContext";
|
|
||||||
|
|
||||||
const {Text, Paragraph} = Typography;
|
|
||||||
const colorList = ['#f0932b', '#badc58', '#6ab04c', '#eb4d4b', '#0abde3', '#9b59b6', '#3498db', '#22a6b3', '#e84393', '#f9ca24'];
|
|
||||||
|
|
||||||
class SingleReview extends React.Component {
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
isPersonalReview: false
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
const {username} = this.props.review;
|
|
||||||
const color = colorList[username.length % 10];
|
|
||||||
this.state = {
|
|
||||||
content: '',
|
|
||||||
rating: 0,
|
|
||||||
color: color,
|
|
||||||
review: props.review
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateCallback = (review) => {
|
|
||||||
this.setState({
|
|
||||||
review
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
deleteReview = () => {
|
|
||||||
const {uuid} = this.props;
|
|
||||||
const {id} = this.state.review;
|
|
||||||
const config = this.props.context;
|
|
||||||
|
|
||||||
let url =window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.store;
|
|
||||||
|
|
||||||
// call as an admin api if the review is not a personal review
|
|
||||||
if (!this.props.isPersonalReview) {
|
|
||||||
url += "/admin";
|
|
||||||
}
|
|
||||||
|
|
||||||
url += "/reviews/" + uuid + "/" + id;
|
|
||||||
|
|
||||||
axios.delete(url).then(res => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
notification["success"]({
|
|
||||||
message: 'Done!',
|
|
||||||
description:
|
|
||||||
'The review has been deleted successfully.',
|
|
||||||
});
|
|
||||||
|
|
||||||
this.props.deleteCallback(id);
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
if (error.hasOwnProperty("response") && error.response.status === 401) {
|
|
||||||
window.location.href = window.location.origin+ '/store/login';
|
|
||||||
} else {
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"We were unable to delete the review..",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {isEditable, isDeletable, uuid} = this.props;
|
|
||||||
const {color, review} = this.state;
|
|
||||||
const {content, rating, username} = review;
|
|
||||||
const avatarLetter = username.charAt(0).toUpperCase();
|
|
||||||
const body = (
|
|
||||||
<div style={{marginTop: -5}}>
|
|
||||||
<StarRatings
|
|
||||||
rating={rating}
|
|
||||||
starRatedColor="#777"
|
|
||||||
starDimension="12px"
|
|
||||||
starSpacing="2px"
|
|
||||||
numberOfStars={5}
|
|
||||||
name='rating'
|
|
||||||
/>
|
|
||||||
<Text style={{fontSize: 12, color: "#aaa"}} type="secondary"> {review.createdAt}</Text><br/>
|
|
||||||
<Paragraph style={{color: "#777"}}>
|
|
||||||
<Twemoji options={{className: 'twemoji'}}>
|
|
||||||
{content}
|
|
||||||
</Twemoji>
|
|
||||||
</Paragraph>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const title = (
|
|
||||||
<div>
|
|
||||||
{review.username}
|
|
||||||
{isEditable && (<EditReview uuid={uuid} review={review} updateCallback={this.updateCallback}/>)}
|
|
||||||
{isDeletable && (
|
|
||||||
<Popconfirm
|
|
||||||
title="Are you sure delete this review?"
|
|
||||||
onConfirm={this.deleteReview}
|
|
||||||
okText="Yes"
|
|
||||||
cancelText="No"
|
|
||||||
>
|
|
||||||
<span className="delete-button">delete</span>
|
|
||||||
</Popconfirm>)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<List.Item.Meta
|
|
||||||
avatar={
|
|
||||||
<Avatar style={{backgroundColor: color, verticalAlign: 'middle'}} size="large">
|
|
||||||
{avatarLetter}
|
|
||||||
</Avatar>
|
|
||||||
}
|
|
||||||
title={title}
|
|
||||||
description={body}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withConfigContext(SingleReview);
|
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.edit-button {
|
|
||||||
color: #1890ff;
|
|
||||||
text-decoration: none;
|
|
||||||
outline: none;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 0.8em;
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
@ -1,191 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {Drawer, Button, Icon, Row, Col, Typography, Divider, Input, Spin, notification} from 'antd';
|
|
||||||
import StarRatings from "react-star-ratings";
|
|
||||||
import axios from "axios";
|
|
||||||
import "./EditReview.css";
|
|
||||||
import {withConfigContext} from "../../../../../../context/ConfigContext";
|
|
||||||
|
|
||||||
const {Title} = Typography;
|
|
||||||
const {TextArea} = Input;
|
|
||||||
|
|
||||||
class EditReview extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
visible: false,
|
|
||||||
content: '',
|
|
||||||
rating: 0,
|
|
||||||
loading: false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const {content,rating,id} = this.props.review;
|
|
||||||
console.log(this.props.review);
|
|
||||||
this.setState({
|
|
||||||
content,
|
|
||||||
rating
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
showDrawer = () => {
|
|
||||||
this.setState({
|
|
||||||
visible: true,
|
|
||||||
loading: false
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onClose = () => {
|
|
||||||
this.setState({
|
|
||||||
visible: false,
|
|
||||||
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
changeRating = (newRating, name) => {
|
|
||||||
this.setState({
|
|
||||||
rating: newRating
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onChange = (e) => {
|
|
||||||
this.setState({content: e.target.value})
|
|
||||||
};
|
|
||||||
|
|
||||||
onSubmit = () => {
|
|
||||||
const config = this.props.context;
|
|
||||||
const {content, rating} = this.state;
|
|
||||||
const {id} = this.props.review;
|
|
||||||
const {uuid} = this.props;
|
|
||||||
this.setState({
|
|
||||||
loading: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
content: content,
|
|
||||||
rating: rating
|
|
||||||
};
|
|
||||||
|
|
||||||
axios.put(
|
|
||||||
window.location.origin+ config.serverConfig.invoker.uri + config.serverConfig.invoker.store + "/reviews/" + uuid+"/"+id,
|
|
||||||
payload,
|
|
||||||
).then(res => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
notification["success"]({
|
|
||||||
message: 'Done!',
|
|
||||||
description:
|
|
||||||
'Your review has been update successfully.',
|
|
||||||
});
|
|
||||||
|
|
||||||
this.props.updateCallback(res.data.data);
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"We are unable to update your review right now.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
if (error.hasOwnProperty("response") && error.response.status === 401) {
|
|
||||||
window.location.href = window.location.origin+ '/store/login';
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"We are unable to add your review right now.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
<span className="edit-button" onClick={this.showDrawer}>edit</span>
|
|
||||||
<Drawer
|
|
||||||
// title="Basic Drawer"
|
|
||||||
placement="bottom"
|
|
||||||
closable={false}
|
|
||||||
onClose={this.onClose}
|
|
||||||
visible={this.state.visible}
|
|
||||||
height={400}
|
|
||||||
>
|
|
||||||
<Spin spinning={this.state.loading} tip="Posting your review...">
|
|
||||||
<Row>
|
|
||||||
<Col lg={8}/>
|
|
||||||
<Col lg={8}>
|
|
||||||
<Title level={4}>Edit review</Title>
|
|
||||||
<Divider/>
|
|
||||||
<TextArea
|
|
||||||
placeholder="Tell others what you think about this app. Would you recommend it, and why?"
|
|
||||||
onChange={this.onChange}
|
|
||||||
rows={6}
|
|
||||||
value={this.state.content || ''}
|
|
||||||
style={{marginBottom: 20}}
|
|
||||||
/>
|
|
||||||
<StarRatings
|
|
||||||
rating={this.state.rating}
|
|
||||||
changeRating={this.changeRating}
|
|
||||||
starRatedColor="#777"
|
|
||||||
starHoverColor="#444"
|
|
||||||
starDimension="20px"
|
|
||||||
starSpacing="2px"
|
|
||||||
numberOfStars={5}
|
|
||||||
name='rating'
|
|
||||||
/>
|
|
||||||
<br/><br/>
|
|
||||||
<Button onClick={this.onClose} style={{marginRight: 8}}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button disabled={this.state.rating === 0} onClick={this.onSubmit} type="primary">
|
|
||||||
Submit
|
|
||||||
</Button>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Spin>
|
|
||||||
</Drawer>
|
|
||||||
|
|
||||||
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withConfigContext(EditReview);
|
|
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Entgra (pvt) Ltd. 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 {Layout, Menu, Icon} from 'antd';
|
||||||
|
import {Switch, Link} from "react-router-dom";
|
||||||
|
import RouteWithSubRoutes from "../../components/RouteWithSubRoutes"
|
||||||
|
import {Redirect} from 'react-router'
|
||||||
|
import "../../App.css";
|
||||||
|
import {withConfigContext} from "../../context/ConfigContext";
|
||||||
|
import Logout from "./Logout/Logout";
|
||||||
|
|
||||||
|
const {Header, Content, Footer} = Layout;
|
||||||
|
const {SubMenu} = Menu;
|
||||||
|
|
||||||
|
|
||||||
|
class Dashboard extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
routes: props.routes,
|
||||||
|
selectedKeys: [],
|
||||||
|
deviceTypes: []
|
||||||
|
};
|
||||||
|
this.logo = this.props.context.theme.logo;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Layout className="layout">
|
||||||
|
<Header style={{paddingLeft: 0, paddingRight: 0}}>
|
||||||
|
<div className="logo-image">
|
||||||
|
<img alt="logo" src={this.logo}/>
|
||||||
|
</div>
|
||||||
|
<Menu
|
||||||
|
theme="light"
|
||||||
|
mode="horizontal"
|
||||||
|
defaultSelectedKeys={['1']}
|
||||||
|
style={{lineHeight: '64px'}}
|
||||||
|
>
|
||||||
|
<Menu.Item key="devices"><Link to="/entgra/devices"><Icon type="appstore"/>Devices</Link></Menu.Item>
|
||||||
|
<Menu.Item key="geo"><Link to="/entgra/geo"><Icon type="environment"/>Geo</Link></Menu.Item>
|
||||||
|
<Menu.Item key="reports"><Link to="/entgra/reports"><Icon type="bar-chart"/>Reports</Link></Menu.Item>
|
||||||
|
|
||||||
|
<SubMenu className="profile"
|
||||||
|
title={
|
||||||
|
<span className="submenu-title-wrapper">
|
||||||
|
<Icon type="user"/>
|
||||||
|
Profile
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Logout/>
|
||||||
|
</SubMenu>
|
||||||
|
|
||||||
|
</Menu>
|
||||||
|
|
||||||
|
</Header>
|
||||||
|
</Layout>
|
||||||
|
<Layout>
|
||||||
|
<Content style={{marginTop: 2}}>
|
||||||
|
<Switch>
|
||||||
|
<Redirect exact from="/entgra" to="/entgra/devices"/>
|
||||||
|
{this.state.routes.map((route) => (
|
||||||
|
<RouteWithSubRoutes key={route.path} {...route} />
|
||||||
|
))}
|
||||||
|
</Switch>
|
||||||
|
</Content>
|
||||||
|
<Footer style={{textAlign: 'center'}}>
|
||||||
|
©2019 entgra.io
|
||||||
|
</Footer>
|
||||||
|
</Layout>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default withConfigContext(Dashboard);
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Entgra (pvt) Ltd. 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 {
|
||||||
|
PageHeader,
|
||||||
|
Typography,
|
||||||
|
Breadcrumb,
|
||||||
|
Icon,
|
||||||
|
Card
|
||||||
|
} from "antd";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
import DeviceTable from "../../../components/Devices/DevicesTable";
|
||||||
|
|
||||||
|
const {Paragraph} = Typography;
|
||||||
|
|
||||||
|
class Devices extends React.Component {
|
||||||
|
routes;
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.routes = props.routes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PageHeader style={{paddingTop: 0}}>
|
||||||
|
<Breadcrumb style={{paddingBottom: 16}}>
|
||||||
|
<Breadcrumb.Item>
|
||||||
|
<Link to="/entgra/devices"><Icon type="home"/> Home</Link>
|
||||||
|
</Breadcrumb.Item>
|
||||||
|
<Breadcrumb.Item>Devices</Breadcrumb.Item>
|
||||||
|
</Breadcrumb>
|
||||||
|
<div className="wrap">
|
||||||
|
<h3>Devices</h3>
|
||||||
|
<Paragraph>Lorem ipsum dolor sit amet, est similique constituto at, quot inermis id mel, an
|
||||||
|
illud incorrupte nam.</Paragraph>
|
||||||
|
</div>
|
||||||
|
</PageHeader>
|
||||||
|
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||||
|
<div style={{backgroundColor:"#ffffff", borderRadius: 5}}>
|
||||||
|
<DeviceTable/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Devices;
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Entgra (pvt) Ltd. 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 {
|
||||||
|
PageHeader,
|
||||||
|
Typography,
|
||||||
|
Breadcrumb,
|
||||||
|
Icon,
|
||||||
|
Card
|
||||||
|
} from "antd";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
import DeviceTable from "../../../components/Devices/DevicesTable";
|
||||||
|
|
||||||
|
const {Paragraph} = Typography;
|
||||||
|
|
||||||
|
class Geo extends React.Component {
|
||||||
|
routes;
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.routes = props.routes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PageHeader style={{paddingTop: 0}}>
|
||||||
|
<Breadcrumb style={{paddingBottom: 16}}>
|
||||||
|
<Breadcrumb.Item>
|
||||||
|
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||||
|
</Breadcrumb.Item>
|
||||||
|
<Breadcrumb.Item>Geo</Breadcrumb.Item>
|
||||||
|
</Breadcrumb>
|
||||||
|
<div className="wrap">
|
||||||
|
<h3>Geo</h3>
|
||||||
|
<Paragraph>Lorem ipsum dolor sit amet, est similique constituto at, quot inermis id mel, an
|
||||||
|
illud incorrupte nam.</Paragraph>
|
||||||
|
</div>
|
||||||
|
</PageHeader>
|
||||||
|
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Geo;
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Entgra (pvt) Ltd. 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 {
|
||||||
|
PageHeader,
|
||||||
|
Typography,
|
||||||
|
Breadcrumb,
|
||||||
|
Icon,
|
||||||
|
Card
|
||||||
|
} from "antd";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
import DeviceTable from "../../../components/Devices/DevicesTable";
|
||||||
|
|
||||||
|
const {Paragraph} = Typography;
|
||||||
|
|
||||||
|
class Reports extends React.Component {
|
||||||
|
routes;
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.routes = props.routes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<PageHeader style={{paddingTop: 0}}>
|
||||||
|
<Breadcrumb style={{paddingBottom: 16}}>
|
||||||
|
<Breadcrumb.Item>
|
||||||
|
<Link to="/entgra"><Icon type="home"/> Home</Link>
|
||||||
|
</Breadcrumb.Item>
|
||||||
|
<Breadcrumb.Item>Reports</Breadcrumb.Item>
|
||||||
|
</Breadcrumb>
|
||||||
|
<div className="wrap">
|
||||||
|
<h3>Reports</h3>
|
||||||
|
<Paragraph>Lorem ipsum dolor sit amet, est similique constituto at, quot inermis id mel, an
|
||||||
|
illud incorrupte nam.</Paragraph>
|
||||||
|
</div>
|
||||||
|
</PageHeader>
|
||||||
|
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Reports;
|
@ -1,157 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {Layout, Menu, Icon} from 'antd';
|
|
||||||
|
|
||||||
const {Header, Content, Footer} = Layout;
|
|
||||||
import {Link} from "react-router-dom";
|
|
||||||
import RouteWithSubRoutes from "../../components/RouteWithSubRoutes";
|
|
||||||
import {Switch} from 'react-router';
|
|
||||||
import axios from "axios";
|
|
||||||
import "../../App.css";
|
|
||||||
import {withConfigContext} from "../../context/ConfigContext";
|
|
||||||
import Logout from "./logout/Logout";
|
|
||||||
|
|
||||||
const {SubMenu} = Menu;
|
|
||||||
|
|
||||||
class Dashboard extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
routes: props.routes,
|
|
||||||
selectedKeys: [],
|
|
||||||
deviceTypes: []
|
|
||||||
};
|
|
||||||
this.logo = this.props.context.theme.logo;
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.getDeviceTypes();
|
|
||||||
}
|
|
||||||
|
|
||||||
getDeviceTypes = () => {
|
|
||||||
const config = this.props.context;
|
|
||||||
axios.get(
|
|
||||||
window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.deviceMgt + "/device-types"
|
|
||||||
).then(res => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
const deviceTypes = JSON.parse(res.data.data);
|
|
||||||
this.setState({
|
|
||||||
deviceTypes,
|
|
||||||
loading: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => {
|
|
||||||
if (error.hasOwnProperty("response") && error.response.status === 401) {
|
|
||||||
window.location.href = window.location.origin + '/store/login';
|
|
||||||
} else {
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"Error occurred while trying to load device types.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
loading: false
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
changeSelectedMenuItem = (key) => {
|
|
||||||
this.setState({
|
|
||||||
selectedKeys: [key]
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const config = this.props.context;
|
|
||||||
const {selectedKeys, deviceTypes} = this.state;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Layout className="layout">
|
|
||||||
<Header style={{paddingLeft: 0, paddingRight: 0}}>
|
|
||||||
<div className="logo-image">
|
|
||||||
<img alt="logo" src={this.logo}/>
|
|
||||||
</div>
|
|
||||||
<Menu
|
|
||||||
theme="light"
|
|
||||||
mode="horizontal"
|
|
||||||
defaultSelectedKeys={selectedKeys}
|
|
||||||
style={{lineHeight: '64px'}}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
deviceTypes.map((deviceType) => {
|
|
||||||
const platform = deviceType.name;
|
|
||||||
const defaultPlatformIcons = config.defaultPlatformIcons;
|
|
||||||
let icon = defaultPlatformIcons.default.icon;
|
|
||||||
let theme = defaultPlatformIcons.default.theme;
|
|
||||||
if (defaultPlatformIcons.hasOwnProperty(platform)) {
|
|
||||||
icon = defaultPlatformIcons[platform].icon;
|
|
||||||
theme = defaultPlatformIcons[platform].theme;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Menu.Item key={platform}>
|
|
||||||
<Link to={"/store/" + platform}>
|
|
||||||
<Icon type={icon} theme={theme}/>
|
|
||||||
{platform}
|
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
<Menu.Item key="web-clip"><Link to="/store/web-clip"><Icon type="upload"/>Web
|
|
||||||
Clips</Link></Menu.Item>
|
|
||||||
|
|
||||||
<SubMenu className="profile"
|
|
||||||
title={
|
|
||||||
<span className="submenu-title-wrapper">
|
|
||||||
<Icon type="user"/>
|
|
||||||
Profile
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Logout/>
|
|
||||||
</SubMenu>
|
|
||||||
</Menu>
|
|
||||||
</Header>
|
|
||||||
</Layout>
|
|
||||||
<Layout>
|
|
||||||
<Content style={{padding: '0 0'}}>
|
|
||||||
<Switch>
|
|
||||||
{this.state.routes.map((route) => (
|
|
||||||
<RouteWithSubRoutes changeSelectedMenuItem={this.changeSelectedMenuItem}
|
|
||||||
key={route.path} {...route} />
|
|
||||||
))}
|
|
||||||
|
|
||||||
</Switch>
|
|
||||||
|
|
||||||
</Content>
|
|
||||||
<Footer style={{textAlign: 'center'}}>
|
|
||||||
©2019 entgra.io
|
|
||||||
</Footer>
|
|
||||||
</Layout>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default withConfigContext(Dashboard);
|
|
@ -1,353 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {
|
|
||||||
PageHeader,
|
|
||||||
Typography,
|
|
||||||
Card,
|
|
||||||
Steps,
|
|
||||||
Button,
|
|
||||||
message,
|
|
||||||
Row,
|
|
||||||
Col,
|
|
||||||
Tag,
|
|
||||||
Tooltip,
|
|
||||||
Input,
|
|
||||||
Icon,
|
|
||||||
Select,
|
|
||||||
Switch,
|
|
||||||
Form,
|
|
||||||
Upload,
|
|
||||||
Divider
|
|
||||||
} from "antd";
|
|
||||||
import Step1 from "./Step1";
|
|
||||||
import Step2 from "./Step2";
|
|
||||||
import Step3 from "./Step3";
|
|
||||||
import styles from "./Style.less";
|
|
||||||
import IconImage from "./IconImg";
|
|
||||||
import UploadScreenshots from "./UploadScreenshots";
|
|
||||||
|
|
||||||
const Paragraph = Typography;
|
|
||||||
const Dragger = Upload.Dragger;
|
|
||||||
const routes = [
|
|
||||||
{
|
|
||||||
path: 'index',
|
|
||||||
breadcrumbName: 'store',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'first',
|
|
||||||
breadcrumbName: 'dashboard',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'second',
|
|
||||||
breadcrumbName: 'add new app',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const props = {
|
|
||||||
name: 'file',
|
|
||||||
multiple: false,
|
|
||||||
action: '//jsonplaceholder.typicode.com/posts/',
|
|
||||||
onChange(info) {
|
|
||||||
const status = info.file.status;
|
|
||||||
if (status !== 'uploading') {
|
|
||||||
// console.log(info.file, info.fileList);
|
|
||||||
}
|
|
||||||
if (status === 'done') {
|
|
||||||
message.success(`${info.file.name} file uploaded successfully.`);
|
|
||||||
} else if (status === 'error') {
|
|
||||||
message.error(`${info.file.name} file upload failed.`);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const Step = Steps.Step;
|
|
||||||
|
|
||||||
const steps = [{
|
|
||||||
title: 'First',
|
|
||||||
content: Step1
|
|
||||||
}, {
|
|
||||||
title: 'Second',
|
|
||||||
content: Step2,
|
|
||||||
}, {
|
|
||||||
title: 'Last',
|
|
||||||
content: Step3,
|
|
||||||
}];
|
|
||||||
|
|
||||||
|
|
||||||
const {Option} = Select;
|
|
||||||
const {TextArea} = Input;
|
|
||||||
const InputGroup = Input.Group;
|
|
||||||
|
|
||||||
const formItemLayout = {
|
|
||||||
labelCol: {
|
|
||||||
span: 4,
|
|
||||||
},
|
|
||||||
wrapperCol: {
|
|
||||||
span: 20,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class EditableTagGroup extends React.Component {
|
|
||||||
state = {
|
|
||||||
tags: [],
|
|
||||||
inputVisible: false,
|
|
||||||
inputValue: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
handleClose = (removedTag) => {
|
|
||||||
const tags = this.state.tags.filter(tag => tag !== removedTag);
|
|
||||||
// console.log(tags);
|
|
||||||
this.setState({tags});
|
|
||||||
}
|
|
||||||
|
|
||||||
showInput = () => {
|
|
||||||
this.setState({inputVisible: true}, () => this.input.focus());
|
|
||||||
}
|
|
||||||
|
|
||||||
handleInputChange = (e) => {
|
|
||||||
this.setState({inputValue: e.target.value});
|
|
||||||
}
|
|
||||||
|
|
||||||
handleInputConfirm = () => {
|
|
||||||
const {inputValue} = this.state;
|
|
||||||
let {tags} = this.state;
|
|
||||||
if (inputValue && tags.indexOf(inputValue) === -1) {
|
|
||||||
tags = [...tags, inputValue];
|
|
||||||
}
|
|
||||||
// console.log(tags);
|
|
||||||
this.setState({
|
|
||||||
tags,
|
|
||||||
inputVisible: false,
|
|
||||||
inputValue: '',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
saveInputRef = input => this.input = input
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {tags, inputVisible, inputValue} = this.state;
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{tags.map((tag, index) => {
|
|
||||||
const isLongTag = tag.length > 20;
|
|
||||||
const tagElem = (
|
|
||||||
<Tag key={tag} closable={index !== 0} onClose={() => this.handleClose(tag)}>
|
|
||||||
{isLongTag ? `${tag.slice(0, 20)}...` : tag}
|
|
||||||
</Tag>
|
|
||||||
);
|
|
||||||
return isLongTag ? <Tooltip title={tag} key={tag}>{tagElem}</Tooltip> : tagElem;
|
|
||||||
})}
|
|
||||||
{inputVisible && (
|
|
||||||
<Input
|
|
||||||
ref={this.saveInputRef}
|
|
||||||
type="text"
|
|
||||||
size="small"
|
|
||||||
style={{width: 78}}
|
|
||||||
value={inputValue}
|
|
||||||
onChange={this.handleInputChange}
|
|
||||||
onBlur={this.handleInputConfirm}
|
|
||||||
onPressEnter={this.handleInputConfirm}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!inputVisible && (
|
|
||||||
<Tag
|
|
||||||
onClick={this.showInput}
|
|
||||||
style={{background: '#fff', borderStyle: 'dashed'}}
|
|
||||||
>
|
|
||||||
<Icon type="plus"/> New Tag
|
|
||||||
</Tag>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AddNewApp extends React.Component {
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
current: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
tags = [];
|
|
||||||
|
|
||||||
addTag(key, value){
|
|
||||||
this.tags.push(<Option key={key}>{value}</Option>);
|
|
||||||
}
|
|
||||||
|
|
||||||
next() {
|
|
||||||
const current = this.state.current + 1;
|
|
||||||
this.setState({current});
|
|
||||||
}
|
|
||||||
|
|
||||||
prev() {
|
|
||||||
const current = this.state.current - 1;
|
|
||||||
this.setState({current});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {current} = this.state;
|
|
||||||
const Content = steps[current].content;
|
|
||||||
this.addTag('1','Lorem');
|
|
||||||
this.addTag('2','Ipsum');
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<PageHeader
|
|
||||||
title="Add New App"
|
|
||||||
breadcrumb={{routes}}
|
|
||||||
>
|
|
||||||
<div className="wrap">
|
|
||||||
<div className="content">
|
|
||||||
<Paragraph>
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempo.
|
|
||||||
</Paragraph>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</PageHeader>
|
|
||||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 720}}>
|
|
||||||
<Row>
|
|
||||||
<Col span={20} offset={2}>
|
|
||||||
<Card>
|
|
||||||
<Row>
|
|
||||||
<Col span={12}>
|
|
||||||
<div>
|
|
||||||
<Form labelAlign="left" layout="horizontal" className={styles.stepForm}
|
|
||||||
hideRequiredMark>
|
|
||||||
<Form.Item {...formItemLayout} label="Platform">
|
|
||||||
<Select placeholder="ex: android">
|
|
||||||
<Option value="Android">Android</Option>
|
|
||||||
<Option value="iOS">iOS</Option>
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Type">
|
|
||||||
<Select value="Enterprise">
|
|
||||||
<Option value="Enterprise" selected>Enterprise</Option>
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="App Name">
|
|
||||||
<Input placeholder="ex: Lorem App"/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Description">
|
|
||||||
<TextArea placeholder="Enter the description..." rows={7}/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Category">
|
|
||||||
<Select placeholder="Select a category">
|
|
||||||
<Option value="travel">Travel</Option>
|
|
||||||
<Option value="entertainment">Entertainment</Option>
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Price">
|
|
||||||
<Input prefix="$" placeholder="00.00"/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Is Sahred?">
|
|
||||||
<Switch checkedChildren={<Icon type="check" />} unCheckedChildren={<Icon type="close" />} defaultChecked />
|
|
||||||
</Form.Item>
|
|
||||||
<Divider/>
|
|
||||||
<Form.Item {...formItemLayout} label="Tags">
|
|
||||||
|
|
||||||
<InputGroup>
|
|
||||||
<Row gutter={8}>
|
|
||||||
<Col span={22}>
|
|
||||||
<Select
|
|
||||||
mode="multiple"
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
placeholder="Tags Mode"
|
|
||||||
>
|
|
||||||
{this.tags}
|
|
||||||
</Select>
|
|
||||||
</Col>
|
|
||||||
<Col span={2}>
|
|
||||||
<Button type="dashed" shape="circle" icon="plus"/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</InputGroup>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Meta Daa">
|
|
||||||
<InputGroup>
|
|
||||||
<Row gutter={8}>
|
|
||||||
<Col span={10}>
|
|
||||||
<Input placeholder="Key"/>
|
|
||||||
</Col>
|
|
||||||
<Col span={12}>
|
|
||||||
<Input placeholder="value"/>
|
|
||||||
</Col>
|
|
||||||
<Col span={2}>
|
|
||||||
<Button type="dashed" shape="circle" icon="plus"/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</InputGroup>
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</div>
|
|
||||||
</Col>
|
|
||||||
<Col span={12} style={{paddingTop: 40, paddingLeft: 20}}>
|
|
||||||
<p>Application</p>
|
|
||||||
<div style={{height: 170}}>
|
|
||||||
<Dragger {...props}>
|
|
||||||
<p className="ant-upload-drag-icon">
|
|
||||||
<Icon type="inbox"/>
|
|
||||||
</p>
|
|
||||||
<p className="ant-upload-text">Click or drag file to this area to
|
|
||||||
upload</p>
|
|
||||||
<p className="ant-upload-hint">Support for a single or bulk upload.
|
|
||||||
Strictly prohibit from uploading company data or other band
|
|
||||||
files</p>
|
|
||||||
</Dragger>
|
|
||||||
</div>
|
|
||||||
<Row style={{marginTop: 40}}>
|
|
||||||
<Col span={12}>
|
|
||||||
<p>Icon</p>
|
|
||||||
<IconImage/>
|
|
||||||
</Col>
|
|
||||||
<Col span={12}>
|
|
||||||
<p>Banner</p>
|
|
||||||
<IconImage/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
|
|
||||||
|
|
||||||
<Row style={{marginTop: 40}}>
|
|
||||||
<Col span={24}>
|
|
||||||
<p>Screenshots</p>
|
|
||||||
<UploadScreenshots/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
|
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AddNewApp;
|
|
@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 { Upload, Icon, message } from 'antd';
|
|
||||||
|
|
||||||
function getBase64(img, callback) {
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.addEventListener('load', () => callback(reader.result));
|
|
||||||
reader.readAsDataURL(img);
|
|
||||||
}
|
|
||||||
|
|
||||||
function beforeUpload(file) {
|
|
||||||
const isJPG = file.type === 'image/jpeg';
|
|
||||||
if (!isJPG) {
|
|
||||||
message.error('You can only upload JPG file!');
|
|
||||||
}
|
|
||||||
const isLt2M = file.size / 1024 / 1024 < 2;
|
|
||||||
if (!isLt2M) {
|
|
||||||
message.error('Image must smaller than 2MB!');
|
|
||||||
}
|
|
||||||
return isJPG && isLt2M;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class IconImage extends React.Component {
|
|
||||||
state = {
|
|
||||||
loading: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChange = (info) => {
|
|
||||||
if (info.file.status === 'uploading') {
|
|
||||||
this.setState({ loading: true });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (info.file.status === 'done') {
|
|
||||||
// Get this url from response in real world.
|
|
||||||
getBase64(info.file.originFileObj, imageUrl => this.setState({
|
|
||||||
imageUrl,
|
|
||||||
loading: false,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const uploadButton = (
|
|
||||||
<div>
|
|
||||||
<Icon type={this.state.loading ? 'loading' : 'plus'} />
|
|
||||||
<div className="ant-upload-text">Upload</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
const imageUrl = this.state.imageUrl;
|
|
||||||
return (
|
|
||||||
<Upload
|
|
||||||
name="avatar"
|
|
||||||
listType="picture-card"
|
|
||||||
className="avatar-uploader"
|
|
||||||
showUploadList={false}
|
|
||||||
action="//jsonplaceholder.typicode.com/posts/"
|
|
||||||
beforeUpload={beforeUpload}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
>
|
|
||||||
{imageUrl ? <img src={imageUrl} alt="avatar" /> : uploadButton}
|
|
||||||
</Upload>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default IconImage;
|
|
@ -1,170 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 {Form, Input, Button, Select, Divider, Tag, Tooltip, Icon, Checkbox, Row, Col} from "antd";
|
|
||||||
import styles from './Style.less';
|
|
||||||
|
|
||||||
const { Option } = Select;
|
|
||||||
const { TextArea } = Input;
|
|
||||||
const InputGroup = Input.Group;
|
|
||||||
|
|
||||||
const formItemLayout = {
|
|
||||||
labelCol: {
|
|
||||||
span: 8,
|
|
||||||
},
|
|
||||||
wrapperCol: {
|
|
||||||
span: 16,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
class EditableTagGroup extends React.Component {
|
|
||||||
state = {
|
|
||||||
tags: [],
|
|
||||||
inputVisible: false,
|
|
||||||
inputValue: '',
|
|
||||||
};
|
|
||||||
|
|
||||||
handleClose = (removedTag) => {
|
|
||||||
const tags = this.state.tags.filter(tag => tag !== removedTag);
|
|
||||||
// console.log(tags);
|
|
||||||
this.setState({ tags });
|
|
||||||
}
|
|
||||||
|
|
||||||
showInput = () => {
|
|
||||||
this.setState({ inputVisible: true }, () => this.input.focus());
|
|
||||||
}
|
|
||||||
|
|
||||||
handleInputChange = (e) => {
|
|
||||||
this.setState({ inputValue: e.target.value });
|
|
||||||
}
|
|
||||||
|
|
||||||
handleInputConfirm = () => {
|
|
||||||
const { inputValue } = this.state;
|
|
||||||
let { tags } = this.state;
|
|
||||||
if (inputValue && tags.indexOf(inputValue) === -1) {
|
|
||||||
tags = [...tags, inputValue];
|
|
||||||
}
|
|
||||||
// console.log(tags);
|
|
||||||
this.setState({
|
|
||||||
tags,
|
|
||||||
inputVisible: false,
|
|
||||||
inputValue: '',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
saveInputRef = input => this.input = input
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { tags, inputVisible, inputValue } = this.state;
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{tags.map((tag, index) => {
|
|
||||||
const isLongTag = tag.length > 20;
|
|
||||||
const tagElem = (
|
|
||||||
<Tag key={tag} closable={index !== 0} onClose={() => this.handleClose(tag)}>
|
|
||||||
{isLongTag ? `${tag.slice(0, 20)}...` : tag}
|
|
||||||
</Tag>
|
|
||||||
);
|
|
||||||
return isLongTag ? <Tooltip title={tag} key={tag}>{tagElem}</Tooltip> : tagElem;
|
|
||||||
})}
|
|
||||||
{inputVisible && (
|
|
||||||
<Input
|
|
||||||
ref={this.saveInputRef}
|
|
||||||
type="text"
|
|
||||||
size="small"
|
|
||||||
style={{ width: 78 }}
|
|
||||||
value={inputValue}
|
|
||||||
onChange={this.handleInputChange}
|
|
||||||
onBlur={this.handleInputConfirm}
|
|
||||||
onPressEnter={this.handleInputConfirm}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!inputVisible && (
|
|
||||||
<Tag
|
|
||||||
onClick={this.showInput}
|
|
||||||
style={{ background: '#fff', borderStyle: 'dashed' }}
|
|
||||||
>
|
|
||||||
<Icon type="plus" /> New Tag
|
|
||||||
</Tag>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Step1 extends React.Component {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Form layout="horizontal" className={styles.stepForm} hideRequiredMark>
|
|
||||||
|
|
||||||
<Form.Item {...formItemLayout} label="Platform">
|
|
||||||
<Select placeholder="ex: android">
|
|
||||||
<Option value="Android">Android</Option>
|
|
||||||
<Option value="iOS">iOS</Option>
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Type">
|
|
||||||
<Select value="Enterprise">
|
|
||||||
<Option value="Enterprise" selected>Enterprise</Option>
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Name">
|
|
||||||
<Input placeholder="App Name" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Description">
|
|
||||||
<TextArea placeholder="Enter the description" rows={4} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Category">
|
|
||||||
<Select placeholder="Select a category">
|
|
||||||
<Option value="travel">Travel</Option>
|
|
||||||
<Option value="entertainment">Entertainment</Option>
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Tags">
|
|
||||||
<EditableTagGroup/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Price">
|
|
||||||
<Input prefix="$" placeholder="00.00" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Share with all tenents?">
|
|
||||||
<Checkbox > </Checkbox>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item {...formItemLayout} label="Meta Daa">
|
|
||||||
<InputGroup>
|
|
||||||
<Row gutter={8}>
|
|
||||||
<Col span={5}>
|
|
||||||
<Input placeholder="Key" />
|
|
||||||
</Col>
|
|
||||||
<Col span={10}>
|
|
||||||
<Input placeholder="value" />
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Button type="dashed" shape="circle" icon="plus" />
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</InputGroup>
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Step1;
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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"
|
|
||||||
|
|
||||||
class Step2 extends React.Component {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<p>tttoooeeee</p>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Step2;
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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"
|
|
||||||
|
|
||||||
class Step3 extends React.Component {
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<p>tttoooeeee</p>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Step3;
|
|
@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.stepForm {
|
|
||||||
max-width: 500px;
|
|
||||||
margin: 40px auto 0;
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 { Upload, Icon, Modal} from 'antd';
|
|
||||||
|
|
||||||
|
|
||||||
class UploadScreenshots extends React.Component {
|
|
||||||
state = {
|
|
||||||
previewVisible: false,
|
|
||||||
previewImage: '',
|
|
||||||
fileList: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
handleCancel = () => this.setState({ previewVisible: false });
|
|
||||||
|
|
||||||
handlePreview = (file) => {
|
|
||||||
this.setState({
|
|
||||||
previewImage: file.url || file.thumbUrl,
|
|
||||||
previewVisible: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChange = ({ fileList }) => this.setState({ fileList });
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { previewVisible, previewImage, fileList } = this.state;
|
|
||||||
const uploadButton = (
|
|
||||||
<div>
|
|
||||||
<Icon type="plus" />
|
|
||||||
<div className="ant-upload-text">Upload</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<div className="clearfix">
|
|
||||||
<Upload
|
|
||||||
action="//jsonplaceholder.typicode.com/posts/"
|
|
||||||
listType="picture-card"
|
|
||||||
fileList={fileList}
|
|
||||||
onPreview={this.handlePreview}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
>
|
|
||||||
{fileList.length >= 3 ? null : uploadButton}
|
|
||||||
</Upload>
|
|
||||||
<Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
|
|
||||||
<img alt="example" style={{ width: '100%' }} src={previewImage} />
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default UploadScreenshots;
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 { Upload, Icon, Modal} from 'antd';
|
|
||||||
|
|
||||||
|
|
||||||
class AddTagModal extends React.Component {
|
|
||||||
state = {
|
|
||||||
previewVisible: false,
|
|
||||||
previewImage: '',
|
|
||||||
fileList: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
handleCancel = () => this.setState({ previewVisible: false });
|
|
||||||
|
|
||||||
handlePreview = (file) => {
|
|
||||||
this.setState({
|
|
||||||
previewImage: file.url || file.thumbUrl,
|
|
||||||
previewVisible: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleChange = ({ fileList }) => this.setState({ fileList });
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { previewVisible, previewImage, fileList } = this.state;
|
|
||||||
const uploadButton = (
|
|
||||||
<div>
|
|
||||||
<Icon type="plus" />
|
|
||||||
<div className="ant-upload-text">Upload</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<div className="clearfix">
|
|
||||||
<Upload
|
|
||||||
action="//jsonplaceholder.typicode.com/posts/"
|
|
||||||
listType="picture-card"
|
|
||||||
fileList={fileList}
|
|
||||||
onPreview={this.handlePreview}
|
|
||||||
onChange={this.handleChange}
|
|
||||||
>
|
|
||||||
{fileList.length >= 3 ? null : uploadButton}
|
|
||||||
</Upload>
|
|
||||||
<Modal visible={previewVisible} footer={null} onCancel={this.handleCancel}>
|
|
||||||
<img alt="example" style={{ width: '100%' }} src={previewImage} />
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default AddTagModal;
|
|
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 AppList from "../../../components/apps/AppList";
|
|
||||||
|
|
||||||
class Apps extends React.Component {
|
|
||||||
routes;
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.routes = props.routes;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {deviceType} = this.props.match.params;
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div style={{background: '#f0f2f5', padding: 24, minHeight: 760}}>
|
|
||||||
{deviceType!==null && <AppList changeSelectedMenuItem={this.props.changeSelectedMenuItem} deviceType={deviceType}/>}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Apps;
|
|
@ -1,131 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Entgra (pvt) Ltd. 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 '../../../../App.css';
|
|
||||||
import {Skeleton, Typography, Row, Col, Card, message, notification, Breadcrumb, Icon} from "antd";
|
|
||||||
import ReleaseView from "../../../../components/apps/release/ReleaseView";
|
|
||||||
import axios from "axios";
|
|
||||||
import {withConfigContext} from "../../../../context/ConfigContext";
|
|
||||||
import {Link} from "react-router-dom";
|
|
||||||
|
|
||||||
const {Title} = Typography;
|
|
||||||
|
|
||||||
class Release extends React.Component {
|
|
||||||
routes;
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.routes = props.routes;
|
|
||||||
this.state = {
|
|
||||||
loading: true,
|
|
||||||
app: null,
|
|
||||||
uuid: null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const {uuid, deviceType} = this.props.match.params;
|
|
||||||
this.fetchData(uuid);
|
|
||||||
this.props.changeSelectedMenuItem(deviceType);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
|
||||||
if (prevState.uuid !== this.state.uuid) {
|
|
||||||
const {uuid, deviceType} = this.props.match.params;
|
|
||||||
this.fetchData(uuid);
|
|
||||||
this.props.changeSelectedMenuItem(deviceType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchData = (uuid) => {
|
|
||||||
const config = this.props.context;
|
|
||||||
|
|
||||||
//send request to the invoker
|
|
||||||
axios.get(
|
|
||||||
window.location.origin + config.serverConfig.invoker.uri + config.serverConfig.invoker.store + "/applications/" + uuid,
|
|
||||||
).then(res => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
let app = res.data.data;
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
app: app,
|
|
||||||
loading: false,
|
|
||||||
uuid: uuid
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
if (error.hasOwnProperty("response") && error.response.status === 401) {
|
|
||||||
//todo display a popop with error
|
|
||||||
message.error('You are not logged in');
|
|
||||||
window.location.href = window.location.origin + '/store/login';
|
|
||||||
} else {
|
|
||||||
notification["error"]({
|
|
||||||
message: "There was a problem",
|
|
||||||
duration: 0,
|
|
||||||
description:
|
|
||||||
"Error occurred while trying to load releases.",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({loading: false});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {app, loading} = this.state;
|
|
||||||
const {deviceType} = this.props.match.params;
|
|
||||||
|
|
||||||
let content = <Title level={3}>No Releases Found</Title>;
|
|
||||||
let appName = "loading...";
|
|
||||||
|
|
||||||
if (app != null && app.applicationReleases.length !== 0) {
|
|
||||||
content = <ReleaseView app={app} deviceType={deviceType}/>;
|
|
||||||
appName = app.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div style={{background: '#f0f2f5', minHeight: 780}}>
|
|
||||||
<Row style={{padding: 10}}>
|
|
||||||
<Col lg={4}>
|
|
||||||
|
|
||||||
</Col>
|
|
||||||
<Col lg={16} md={24} style={{padding: 3}}>
|
|
||||||
<Breadcrumb style={{paddingBottom: 16}}>
|
|
||||||
<Breadcrumb.Item>
|
|
||||||
<Link to={"/store/"+deviceType}><Icon type="home"/> {deviceType + " apps"} </Link>
|
|
||||||
</Breadcrumb.Item>
|
|
||||||
<Breadcrumb.Item>{appName}</Breadcrumb.Item>
|
|
||||||
</Breadcrumb>
|
|
||||||
<Card>
|
|
||||||
<Skeleton loading={loading} avatar={{size: 'large'}} active paragraph={{rows: 8}}>
|
|
||||||
{content}
|
|
||||||
</Skeleton>
|
|
||||||
</Card>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default withConfigContext(Release);
|
|
Loading…
Reference in new issue