diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java index bad405cb38..1404c0c912 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/ApplicationManagerImpl.java @@ -2029,8 +2029,8 @@ public class ApplicationManagerImpl implements ApplicationManager { appUnrestrictedRoles = applicationUpdateWrapper.getUnrestrictedRoles(); } else { List addingRoleList = getDifference(applicationUpdateWrapper.getUnrestrictedRoles(), - applicationDTO.getUnrestrictedRoles()); - List removingRoleList = getDifference(applicationDTO.getUnrestrictedRoles(), + appUnrestrictedRoles); + List removingRoleList = getDifference(appUnrestrictedRoles, applicationUpdateWrapper.getUnrestrictedRoles()); if (!addingRoleList.isEmpty()) { visibilityDAO.addUnrestrictedRoles(addingRoleList, applicationId, tenantId); 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 32b5031d6a..3698c5d840 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 @@ -18,6 +18,7 @@ import React from 'react'; import { + Alert, Drawer, Select, Avatar, @@ -84,6 +85,7 @@ const formats = [ class AppDetailsDrawer extends React.Component { constructor(props) { super(props); + this.config = this.props.context; const drawerWidth = window.innerWidth <= 770 ? '80%' : '40%'; this.state = { @@ -92,14 +94,18 @@ class AppDetailsDrawer extends React.Component { description: null, globalCategories: [], globalTags: [], + globalUnrestrictedRoles: [], categories: [], tags: [], + unrestrictedRoles: [], temporaryDescription: null, temporaryCategories: [], temporaryTags: [], + temporaryUnrestrictedRoles: [], isDescriptionEditEnabled: false, isCategoriesEditEnabled: false, isTagsEditEnabled: false, + isUnrestrictedRolesEditEnabled: false, drawer: null, drawerWidth, }; @@ -114,31 +120,39 @@ class AppDetailsDrawer extends React.Component { ) { this.getCategories(); this.getTags(); + this.getUnrestrictedRoles(); } } componentDidUpdate(prevProps, prevState, snapshot) { if (prevProps.app !== this.props.app) { - const { name, description, tags, categories } = this.props.app; + const { + name, + description, + tags, + categories, + unrestrictedRoles, + } = this.props.app; this.setState({ name, description, tags, categories, + unrestrictedRoles, isDescriptionEditEnabled: false, isCategoriesEditEnabled: false, isTagsEditEnabled: false, + isUnrestrictedRolesEditEnabled: false, }); } } getCategories = () => { - const config = this.props.context; axios .get( window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.publisher + + this.config.serverConfig.invoker.uri + + this.config.serverConfig.invoker.publisher + '/applications/categories', ) .then(res => { @@ -171,12 +185,11 @@ class AppDetailsDrawer extends React.Component { }; getTags = () => { - const config = this.props.context; axios .get( window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.publisher + + this.config.serverConfig.invoker.uri + + this.config.serverConfig.invoker.publisher + '/applications/tags', ) .then(res => { @@ -201,17 +214,46 @@ class AppDetailsDrawer extends React.Component { }); }; + getUnrestrictedRoles = () => { + axios + .get( + window.location.origin + + this.config.serverConfig.invoker.uri + + this.config.serverConfig.invoker.deviceMgt + + '/roles', + ) + .then(res => { + if (res.status === 200) { + const globalUnrestrictedRoles = res.data.data.roles; + + this.setState({ + globalUnrestrictedRoles, + loading: false, + }); + } + }) + .catch(error => { + handleApiError( + error, + 'Error occurred while trying to load roles.', + true, + ); + this.setState({ + loading: false, + }); + }); + }; + // change the app name handleNameSave = name => { - const config = this.props.context; const { id } = this.props.app; if (name !== this.state.name && name !== '') { const data = { name: name }; axios .put( window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.publisher + + this.config.serverConfig.invoker.uri + + this.config.serverConfig.invoker.publisher + '/applications/' + id, data, @@ -288,7 +330,6 @@ class AppDetailsDrawer extends React.Component { // change app categories handleCategorySave = () => { - const config = this.props.context; const { id } = this.props.app; const { temporaryCategories, categories } = this.state; @@ -301,8 +342,8 @@ class AppDetailsDrawer extends React.Component { axios .put( window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.publisher + + this.config.serverConfig.invoker.uri + + this.config.serverConfig.invoker.publisher + '/applications/' + id, data, @@ -363,7 +404,6 @@ class AppDetailsDrawer extends React.Component { // change app tags handleTagsSave = () => { - const config = this.props.context; const { id } = this.props.app; const { temporaryTags, tags } = this.state; @@ -376,8 +416,8 @@ class AppDetailsDrawer extends React.Component { axios .put( window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.publisher + + this.config.serverConfig.invoker.uri + + this.config.serverConfig.invoker.publisher + '/applications/' + id, data, @@ -385,6 +425,7 @@ class AppDetailsDrawer extends React.Component { .then(res => { if (res.status === 200) { const app = res.data.data; + this.props.onUpdateApp('tags', temporaryTags); notification.success({ message: 'Saved!', description: 'App tags updated successfully!', @@ -416,9 +457,75 @@ class AppDetailsDrawer extends React.Component { } }; + enableUnrestrictedRolesEdit = () => { + this.setState({ + isUnrestrictedRolesEditEnabled: true, + temporaryUnrestrictedRoles: this.state.unrestrictedRoles, + }); + }; + + disableUnrestrictedRolesEdit = () => { + this.setState({ + isUnrestrictedRolesEditEnabled: false, + }); + }; + + handleUnrestrictedRolesChange = temporaryUnrestrictedRoles => { + this.setState({ temporaryUnrestrictedRoles }); + }; + + handleUnrestrictedRolesSave = () => { + const { id } = this.props.app; + const { temporaryUnrestrictedRoles, unrestrictedRoles } = this.state; + + temporaryUnrestrictedRoles + .filter(x => !unrestrictedRoles.includes(x)) + .concat( + unrestrictedRoles.filter(x => !temporaryUnrestrictedRoles.includes(x)), + ); + + const data = { unrestrictedRoles: temporaryUnrestrictedRoles }; + axios + .put( + window.location.origin + + this.config.serverConfig.invoker.uri + + this.config.serverConfig.invoker.publisher + + '/applications/' + + id, + data, + ) + .then(res => { + if (res.status === 200) { + const app = res.data.data; + this.props.onUpdateApp( + 'unrestrictedRoles', + temporaryUnrestrictedRoles, + ); + notification.success({ + message: 'Saved!', + description: 'App unrestricted roles updated successfully!', + }); + this.setState({ + loading: false, + unrestrictedRoles: app.unrestrictedRoles, + isUnrestrictedRolesEditEnabled: false, + }); + } + }) + .catch(error => { + handleApiError( + error, + 'Error occurred while trying to update unrestricted roles.', + true, + ); + this.setState({ + loading: false, + }); + }); + }; + // handle description save handleDescriptionSave = () => { - const config = this.props.context; const { id } = this.props.app; const { description, temporaryDescription } = this.state; @@ -430,8 +537,8 @@ class AppDetailsDrawer extends React.Component { axios .put( window.location.origin + - config.serverConfig.invoker.uri + - config.serverConfig.invoker.publisher + + this.config.serverConfig.invoker.uri + + this.config.serverConfig.invoker.publisher + '/applications/' + id, data, @@ -469,7 +576,6 @@ class AppDetailsDrawer extends React.Component { }; render() { - const config = this.props.context; const { app, visible, onClose } = this.props; const { name, @@ -478,13 +584,17 @@ class AppDetailsDrawer extends React.Component { isDescriptionEditEnabled, isCategoriesEditEnabled, isTagsEditEnabled, + isUnrestrictedRolesEditEnabled, temporaryDescription, temporaryCategories, temporaryTags, + temporaryUnrestrictedRoles, globalCategories, globalTags, + globalUnrestrictedRoles, categories, tags, + unrestrictedRoles, } = this.state; if (app == null) { return null; @@ -502,7 +612,7 @@ class AppDetailsDrawer extends React.Component { style={{ marginBottom: 10, borderRadius: '28%', - backgroundColor: pSBC(0.5, config.theme.primaryColor), + backgroundColor: pSBC(0.5, this.config.theme.primaryColor), }} > {avatarLetter} @@ -543,9 +653,9 @@ class AppDetailsDrawer extends React.Component { - {config.androidEnterpriseToken !== null && + {this.config.androidEnterpriseToken !== null && isAuthorized( - config.user, + this.config.user, '/permission/admin/device-mgt/enterprise/user/modify', ) && ( @@ -682,7 +792,7 @@ class AppDetailsDrawer extends React.Component { !isDescriptionEditEnabled && ( { return ( @@ -805,7 +915,7 @@ class AppDetailsDrawer extends React.Component { !isTagsEditEnabled && ( )} + + + Unrestricted Roles + + + + ) + } + /> +
+
+ {!unrestrictedRoles.length && ( + + )} + {isUnrestrictedRolesEditEnabled && ( +
+ +
+ + +
+
+ )} + {!isUnrestrictedRolesEditEnabled && ( + + {unrestrictedRoles.map(unrestrictedRole => { + return ( + + {unrestrictedRole} + + ); + })} + + )} +