From 2d0277de3af6f0e3d4ea83cc460f1e422d14cadb Mon Sep 17 00:00:00 2001 From: Jayasanka Weerasinghe Date: Tue, 28 Apr 2020 08:59:16 +0530 Subject: [PATCH] Add app delete and retire functionality to APPM UI --- .../react-app/package.json | 5 +- .../components/DeleteApp/index.js | 102 +++++++++++++++++ .../ManagedConfigurationsIframe/index.js | 70 ++++++++++-- .../components/RetireApp/index.js | 106 ++++++++++++++++++ .../ApssTable/AppDetailsDrawer/index.js | 68 +++++------ .../ApssTable/AppDetailsDrawer/styles.css | 8 ++ 6 files changed, 313 insertions(+), 46 deletions(-) create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/components/DeleteApp/index.js create mode 100644 components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/components/RetireApp/index.js 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 d39cce7d49..df1743f096 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 @@ -11,6 +11,7 @@ "license": "Apache License 2.0", "dependencies": { "@ant-design/dark-theme": "^0.2.2", + "@ant-design/icons": "^4.0.6", "@babel/polyfill": "^7.6.0", "acorn": "^6.2.0", "antd": "^3.23.6", @@ -25,6 +26,7 @@ "fetch": "^1.1.0", "imagemin": "^6.1.0", "keymirror": "^0.1.1", + "lodash.debounce": "latest", "rc-tween-one": "^2.4.1", "react-d3-graph": "^2.1.0", "react-highlight-words": "^0.16.0", @@ -39,8 +41,7 @@ "redux-thunk": "^2.3.0", "shade-blend-color": "^1.0.0", "storm-react-diagrams": "^5.2.1", - "typescript": "^3.6.4", - "lodash.debounce": "latest" + "typescript": "^3.6.4" }, "devDependencies": { "@babel/core": "^7.5.0", diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/components/DeleteApp/index.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/components/DeleteApp/index.js new file mode 100644 index 0000000000..f7c4da1bb3 --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/components/DeleteApp/index.js @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2020, 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 { DeleteOutlined, ExclamationCircleOutlined } from '@ant-design/icons'; +import { Button, Modal, notification, Tooltip } from 'antd'; +import axios from 'axios'; +import { handleApiError } from '../../../../../../../../../../../services/utils/errorHandler'; +import { withConfigContext } from '../../../../../../../../../../../components/ConfigContext'; +import { withRouter } from 'react-router-dom'; +import '../../styles.css'; + +const { confirm } = Modal; + +class DeleteApp extends React.Component { + showModal = () => { + confirm({ + title: 'Are you sure you want to delete this app?', + icon: , + content: + 'You are trying to delete the entire application, by performing this operation all ' + + 'app data, app release data, and all release artifacts will be deleted ' + + 'permanently. Further, please note, this process cannot be undone.', + okText: 'Yes', + okType: 'danger', + cancelText: 'No', + onOk: this.deleteRelease, + }); + }; + + deleteRelease = () => { + const config = this.props.context; + const apiUrl = + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.publisher + + '/admin/applications/' + + this.props.id; + axios + .delete(apiUrl) + .then(res => { + if (res.status === 200) { + notification.success({ + message: 'Successfully deleted the app', + }); + this.props.history.push('/publisher'); + } + }) + .catch(error => { + handleApiError( + error, + 'Something Went wrong when trying to delete the app, Please contact the administrator', + ); + this.setState({ + loading: false, + }); + }); + }; + + render() { + return ( +
+ {this.props.isDeletableApp && ( + + )} + {!this.props.isDeletableApp && ( + + + + )} +
+ ); + } +} + +export default withConfigContext(withRouter(DeleteApp)); diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/components/ManagedConfigurationsIframe/index.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/components/ManagedConfigurationsIframe/index.js index 51bcb905cd..a1921e0c98 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/components/ManagedConfigurationsIframe/index.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/components/ManagedConfigurationsIframe/index.js @@ -17,10 +17,12 @@ */ import React from 'react'; -import { Button, Modal, notification, Spin } from 'antd'; +import { Button, Modal, notification, Popover, Spin, Tooltip } from 'antd'; import axios from 'axios'; import { withConfigContext } from '../../../../../../../../../../../components/ConfigContext'; import { handleApiError } from '../../../../../../../../../../../services/utils/errorHandler'; +import { SettingOutlined, QuestionCircleOutlined } from '@ant-design/icons'; +import '../../styles.css'; class ManagedConfigurationsIframe extends React.Component { constructor(props) { @@ -29,6 +31,7 @@ class ManagedConfigurationsIframe extends React.Component { this.state = { visible: false, loading: false, + isHintVisible: false, }; } @@ -201,26 +204,69 @@ class ManagedConfigurationsIframe extends React.Component { }); }; + handleHintVisibleChange = visible => { + this.setState({ isHintVisible: visible }); + }; + render() { return (
- + {this.props.isEnabled && ( + + )} + {!this.props.isEnabled && ( + + + + )} - -
-
+
+ + If you are developing apps for the enterprise market, you may + need to satisfy particular requirements set by a + organization"s policies. Managed configurations, + previously previously known as application restrictions, allow + the organization"s IT admin to remotely specify settings + for apps. This capability is particularly useful for + organization-approved apps deployed to a work profile. +

+ } + onVisibleChange={this.handleHintVisibleChange} + overlayStyle={{ width: 300 }} + > + +
+ +
+
+
); diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/components/RetireApp/index.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/components/RetireApp/index.js new file mode 100644 index 0000000000..0aab732f3c --- /dev/null +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/components/RetireApp/index.js @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2020, 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 { + EyeInvisibleOutlined, + ExclamationCircleOutlined, +} from '@ant-design/icons'; +import { Button, Modal, notification, Tooltip } from 'antd'; +import axios from 'axios'; +import { handleApiError } from '../../../../../../../../../../../services/utils/errorHandler'; +import { withConfigContext } from '../../../../../../../../../../../components/ConfigContext'; +import { withRouter } from 'react-router-dom'; +import '../../styles.css'; + +const { confirm } = Modal; + +class RetireApp extends React.Component { + showModal = () => { + confirm({ + title: 'Are you sure you want to retire this app?', + icon: , + content: + 'You are trying to retire the entire application, by performing this operation, ' + + 'you will not see the app data or app release data on either publisher or store. ' + + 'Further, please note, this process cannot be undone.', + okText: 'Yes', + okType: 'danger', + cancelText: 'No', + onOk: this.hideApp, + }); + }; + + hideApp = () => { + const config = this.props.context; + const apiUrl = + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.publisher + + '/admin/applications/retire/' + + this.props.id; + axios + .put(apiUrl) + .then(res => { + if (res.status === 200) { + notification.success({ + message: 'Successfully hided the app', + }); + this.props.history.push('/publisher'); + } + }) + .catch(error => { + console.log(error); + handleApiError( + error, + 'Something Went wrong when trying to reitre the app, Please contact the administrator', + ); + this.setState({ + loading: false, + }); + }); + }; + + render() { + return ( +
+ {this.props.isHideableApp && ( + + )} + {!this.props.isHideableApp && ( + + + + )} +
+ ); + } +} + +export default withConfigContext(withRouter(RetireApp)); diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/index.js b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/index.js index 277b5ada8a..12c38e55b7 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/index.js +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.publisher.ui/react-app/src/scenes/Home/scenes/Apps/components/AppList/components/ApssTable/AppDetailsDrawer/index.js @@ -33,6 +33,8 @@ import { Card, Badge, Tooltip, + Dropdown, + Menu, } from 'antd'; import DetailedRating from '../../../../DetailedRating'; import { Link } from 'react-router-dom'; @@ -46,6 +48,9 @@ import ManagedConfigurationsIframe from './components/ManagedConfigurationsIfram import { handleApiError } from '../../../../../../../../../services/utils/errorHandler'; import Authorized from '../../../../../../../../../components/Authorized/Authorized'; import { isAuthorized } from '../../../../../../../../../services/utils/authorizationHandler'; +import { MoreOutlined } from '@ant-design/icons'; +import DeleteApp from './components/DeleteApp'; +import RetireApp from './components/RetireApp'; const { Meta } = Card; const { Text, Title } = Typography; @@ -485,6 +490,7 @@ class AppDetailsDrawer extends React.Component { if (app == null) { return null; } + const { id } = this.props.app; let avatar = null; @@ -527,6 +533,36 @@ class AppDetailsDrawer extends React.Component { visible={visible} > +
+ + + + + + + + {config.androidEnterpriseToken !== null && + isAuthorized( + config.user, + '/permission/admin/device-mgt/enterprise/user/modify', + ) && ( + + + + )} + + } + > + + +
{avatar}
- {/* display manage config button only if the app is public android app*/} - {app.isAndroidEnterpriseApp && - config.androidEnterpriseToken !== null && ( - -
- Set up managed configurations -
-
- - If you are developing apps for the enterprise market, - you may need to satisfy particular requirements set by - a organization's policies. Managed - configurations, previously known as application - restrictions, allow the organization's IT admin - to remotely specify settings for apps. This capability - is particularly useful for organization-approved apps - deployed to a work profile. - -
-
- - - - } - /> - )} Releases