From d0ca2ec16bc9ed2c81a6a72b942277740dccebb5 Mon Sep 17 00:00:00 2001 From: Jayasanka Date: Thu, 27 Jun 2019 16:00:51 +0530 Subject: [PATCH] Completed edit release functionality in APPM UI --- .../react-app/package.json | 1 + .../apps/list-apps/AppDetailsDrawer.js | 587 ++++++++++++++++-- 2 files changed, 524 insertions(+), 64 deletions(-) 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 !== "


") { + const data = {description: temporaryDescription}; + 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, + description: temporaryDescription, + isDescriptionEditEnabled: 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}); + }); + } else { + this.setState({isDescriptionEditEnabled: false}); + } + }; + render() { const {app, visible, onClose} = this.props; + const { + name, loading, description, isDescriptionEditEnabled, isCategoriesEditEnabled, + isTagsEditEnabled, temporaryDescription, temporaryCategories, temporaryTags, + globalCategories, globalTags, categories, tags + } = this.state; if (app == null) { return null; } @@ -23,71 +379,174 @@ class AppDetailsDrawer extends React.Component { onClose={onClose} visible={visible} > -
- - {app.name} -
- - {app.description} - - Categories -
-
- - {app.categories.map(category => { - return ( - - {category} - - ); - })} - - - - Tags -
-
- - {app.tags.map(category => { - return ( - - {category} - - ); - })} - - - Releases - {/*display add new release only if app type is enterprise*/} - {(app.type ==="ENTERPRISE") && ()} -
- ( - - {release.version}} - description={ -
- Status : {release.currentStatus} Release Type {release.releaseType} -
- } + +
+ + {name} +
+ + Description + {!isDescriptionEditEnabled && ( + + + + )} + + {!isDescriptionEditEnabled && ( +
{ReactHtmlParser(description)}
+ )} + + {isDescriptionEditEnabled && ( +
+ - + + +
+ )} + + + Categories + {!isCategoriesEditEnabled && ( + + + )} +
+
+ {isCategoriesEditEnabled && ( +
+ +
+ + +
+
)} - /> - + {!isCategoriesEditEnabled && ( + { + categories.map(category => { + return ( + + {category} + + ); + }) + } + )} + + + + Tags + {!isTagsEditEnabled && ( + + + )} +
+
+ {isTagsEditEnabled && ( +
+ +
+ + +
+
+ )} + {!isTagsEditEnabled && ( + { + tags.map(tag => { + return ( + + {tag} + + ); + }) + } + )} + + + Releases + {/*display add new release only if app type is enterprise*/} + {(app.type === "ENTERPRISE") && ( + )} +
+ ( + + {release.version}} + description={ +
+ Status : {release.currentStatus} Release Type {release.releaseType} +
+ } + /> +
+ )} + /> + - + +
);