diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json index ae0f25ad97b..2a32749daf7 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/package.json @@ -22,6 +22,7 @@ "react-d3-graph": "^2.0.2", "react-dom": "^16.8.4", "react-highlight-words": "^0.16.0", + "react-html-parser": "^2.0.2", "react-infinite-scroller": "^1.2.4", "react-quill": "^1.3.3", "react-router": "latest", diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer.js index b53fc9812a5..e129c4f4cb5 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/components/apps/list-apps/AppDetailsDrawer.js @@ -1,15 +1,371 @@ import React from 'react'; -import {Drawer, Row, Col, Typography, Divider, Tag, Avatar, List, Button, Icon} from 'antd'; +import {Drawer, Select, Col, Typography, Divider, Tag, notification, List, Button, Spin, message, Icon} from 'antd'; import "../../../App.css"; import DetailedRating from "../detailed-rating/DetailedRating"; import {Link} from "react-router-dom"; +import axios from "axios"; +import config from "../../../../public/conf/config.json"; +import ReactQuill from "react-quill"; +import ReactHtmlParser, {processNodes, convertNodeToElement, htmlparser2} from 'react-html-parser'; -const {Text, Title, Paragraph} = Typography; + +const {Text, Title} = Typography; +const {Option} = Select; + +const modules = { + toolbar: [ + ['bold', 'italic', 'underline', 'strike', 'blockquote'], + [{'list': 'ordered'}, {'list': 'bullet'}], + ['link'] + ], +}; + +const formats = [ + 'bold', 'italic', 'underline', 'strike', 'blockquote', + 'list', 'bullet', + 'link' +]; class AppDetailsDrawer extends React.Component { + constructor(props) { + super(props); + this.state = { + loading: false, + name: null, + description: null, + globalCategories: [], + globalTags: [], + categories: [], + tags: [], + temporaryDescription: null, + temporaryCategories: [], + temporaryTags: [], + isDescriptionEditEnabled: false, + isCategoriesEditEnabled: false, + isTagsEditEnabled: false, + }; + } + + componentDidMount() { + this.getCategories(); + this.getTags(); + } + + componentDidUpdate(prevProps, prevState, snapshot) { + if (prevProps.app !== this.props.app) { + const {name, description, tags, categories} = this.props.app; + this.setState({ + name, + description, + tags, + categories, + isDescriptionEditEnabled: false, + isCategoriesEditEnabled: false, + isTagsEditEnabled: false, + }); + } + } + + getCategories = () => { + axios.get( + config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/categories", + { + headers: {'X-Platform': config.serverConfig.platform} + }).then(res => { + if (res.status === 200) { + const categories = JSON.parse(res.data.data); + + const globalCategories = categories.map(category => { + return ( + + ) + }); + + this.setState({ + globalCategories, + loading: false + }); + } + + }).catch((error) => { + if (error.response.status === 401) { + window.location.href = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + '/publisher/login'; + } else { + message.warning('Something went wrong'); + + } + this.setState({ + loading: false + }); + }); + }; + + getTags = () => { + axios.get( + config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/tags", + { + headers: {'X-Platform': config.serverConfig.platform} + }).then(res => { + if (res.status === 200) { + const tags = JSON.parse(res.data.data); + + const globalTags = tags.map(tag => { + return ( + + ) + }); + + this.setState({ + globalTags, + loading: false + }); + } + + }).catch((error) => { + if (error.response.status === 401) { + window.location.href = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + '/publisher/login'; + } else { + message.warning('Something went wrong'); + + } + this.setState({ + loading: false + }); + }); + }; + + + // change the app name + handleNameSave = name => { + const {id} = this.props.app; + if (name !== this.state.name && name !== "") { + const data = {name: name}; + axios.put( + config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/" + id, + data, + { + headers: {'X-Platform': config.serverConfig.platform} + } + ).then(res => { + if (res.status === 200) { + notification["success"]({ + message: 'Saved!' + }); + this.setState({ + loading: false, + name: name, + }); + + } + }).catch((error) => { + if (error.hasOwnProperty("response") && error.response.status === 401) { + message.error('You are not logged in'); + window.location.href = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + '/publisher/login'; + } else { + message.error('Something went wrong... :('); + } + + this.setState({loading: false}); + }); + } + }; + + // handle description change + handleDescriptionChange = (temporaryDescription) => { + this.setState({temporaryDescription}) + }; + + enableDescriptionEdit = () => { + this.setState({ + isDescriptionEditEnabled: true, + temporaryDescription: this.state.description + }); + }; + + disableDescriptionEdit = () => { + this.setState({ + isDescriptionEditEnabled: false, + }); + }; + + enableCategoriesEdit = () => { + this.setState({ + isCategoriesEditEnabled: true, + temporaryCategories: this.state.categories + }); + }; + + disableCategoriesEdit = () => { + this.setState({ + isCategoriesEditEnabled: false, + }); + }; + + + // handle description change + handleCategoryChange = (temporaryCategories) => { + this.setState({temporaryCategories}) + }; + + // change app categories + handleCategorySave = () => { + const {id} = this.props.app; + const {temporaryCategories, categories} = this.state; + + console.log(temporaryCategories); + + const difference = temporaryCategories + .filter(x => !categories.includes(x)) + .concat(categories.filter(x => !temporaryCategories.includes(x))); + + if (difference.length !== 0 && temporaryCategories.length !== 0) { + const data = {categories: temporaryCategories}; + axios.put( + config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/" + id, + data, + { + headers: {'X-Platform': config.serverConfig.platform} + } + ).then(res => { + if (res.status === 200) { + notification["success"]({ + message: 'Saved!' + }); + this.setState({ + loading: false, + categories: temporaryCategories, + isCategoriesEditEnabled: false + }); + + } + }).catch((error) => { + if (error.hasOwnProperty("response") && error.response.status === 401) { + message.error('You are not logged in'); + window.location.href = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + '/publisher/login'; + } else { + message.error('Something went wrong... :('); + } + + this.setState({loading: false}); + }); + } + }; + + enableTagsEdit = () => { + this.setState({ + isTagsEditEnabled: true, + temporaryTags: this.state.tags + }); + }; + + disableTagsEdit = () => { + this.setState({ + isTagsEditEnabled: false, + }); + }; + + // handle description change + handleTagsChange = (temporaryTags) => { + this.setState({temporaryTags}) + }; + + // change app categories + handleTagsSave = () => { + const {id} = this.props.app; + const {temporaryTags, tags} = this.state; + + console.log(temporaryTags); + + const difference = temporaryTags + .filter(x => !tags.includes(x)) + .concat(tags.filter(x => !temporaryTags.includes(x))); + + if (difference.length !== 0 && temporaryTags.length !== 0) { + const data = {tags: temporaryTags}; + axios.put( + config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + config.serverConfig.invoker.uri + config.serverConfig.invoker.publisher + "/applications/" + id, + data, + { + headers: {'X-Platform': config.serverConfig.platform} + } + ).then(res => { + if (res.status === 200) { + notification["success"]({ + message: 'Saved!' + }); + this.setState({ + loading: false, + tags: temporaryTags, + isTagsEditEnabled: false + }); + } + }).catch((error) => { + if (error.hasOwnProperty("response") && error.response.status === 401) { + message.error('You are not logged in'); + window.location.href = config.serverConfig.protocol + "://" + config.serverConfig.hostname + ':' + config.serverConfig.httpsPort + '/publisher/login'; + } else { + message.error('Something went wrong... :('); + } + + this.setState({loading: false}); + }); + } + }; + + //handle description save + handleDescriptionSave = () => { + + const {id} = this.props.app; + const {description, temporaryDescription} = this.state; + + if (temporaryDescription !== description && temporaryDescription !== "