From 65c6703b732cb12d8ff5600935da696694a92c44 Mon Sep 17 00:00:00 2001 From: Vikas Agarwal Date: Wed, 6 Dec 2017 11:49:31 +0530 Subject: [PATCH 1/7] =?UTF-8?q?Github=20issue#1243,=20Connect=20Admin=20ro?= =?UTF-8?q?le=20=E2=80=94=20Added=20support=20for=20=E2=80=98Connect=20Adm?= =?UTF-8?q?in=E2=80=99=20role=20in=20front=20end?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/actions/loadUser.js | 13 ++++++++++++- src/components/TopBar/TopBarContainer.js | 3 ++- src/config/constants.js | 1 + src/projects/actions/loadProjects.js | 4 ++-- src/projects/detail/ProjectDetail.jsx | 4 ++-- .../detail/containers/TeamManagementContainer.jsx | 9 +++++---- src/projects/list/components/Projects/Projects.jsx | 9 +++++++-- 7 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/actions/loadUser.js b/src/actions/loadUser.js index 23f3e1991..2194920ac 100644 --- a/src/actions/loadUser.js +++ b/src/actions/loadUser.js @@ -1,5 +1,14 @@ import _ from 'lodash' -import { ACCOUNTS_APP_CONNECTOR_URL, LOAD_USER_SUCCESS, LOAD_USER_FAILURE, ROLE_ADMINISTRATOR, ROLE_CONNECT_COPILOT, ROLE_TOPCODER_USER, ROLE_CONNECT_MANAGER } from '../config/constants' +import { + ACCOUNTS_APP_CONNECTOR_URL, + LOAD_USER_SUCCESS, + LOAD_USER_FAILURE, + ROLE_ADMINISTRATOR, + ROLE_CONNECT_COPILOT, + ROLE_TOPCODER_USER, + ROLE_CONNECT_MANAGER, + ROLE_CONNECT_ADMIN +} from '../config/constants' import { getFreshToken, configureConnector, decodeToken } from 'tc-accounts' import { getUserProfile } from '../api/users' import { EventTypes } from 'redux-segment' @@ -46,6 +55,8 @@ export function loadUserSuccess(dispatch, token) { let userRole if (_.indexOf(currentUser.roles, ROLE_ADMINISTRATOR) > -1) { userRole = ROLE_ADMINISTRATOR + } else if (_.indexOf(currentUser.roles, ROLE_CONNECT_ADMIN) > -1) { + userRole = ROLE_CONNECT_ADMIN } else if (_.indexOf(currentUser.roles, ROLE_CONNECT_MANAGER) > -1) { userRole = ROLE_CONNECT_MANAGER } else if (_.indexOf(currentUser.roles, ROLE_CONNECT_COPILOT) > -1) { diff --git a/src/components/TopBar/TopBarContainer.js b/src/components/TopBar/TopBarContainer.js index a2fb81386..daf80a6cf 100644 --- a/src/components/TopBar/TopBarContainer.js +++ b/src/components/TopBar/TopBarContainer.js @@ -10,6 +10,7 @@ import { ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER, ROLE_ADMINISTRATOR, + ROLE_CONNECT_ADMIN, DOMAIN } from '../../config/constants' require('./TopBarContainer.scss') @@ -122,7 +123,7 @@ class TopBarContainer extends React.Component { const mapStateToProps = ({ loadUser }) => { let isPowerUser = false - const roles = [ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER, ROLE_ADMINISTRATOR] + const roles = [ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER, ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN] if (loadUser.user) { isPowerUser = loadUser.user.roles.some((role) => roles.indexOf(role) !== -1) } diff --git a/src/config/constants.js b/src/config/constants.js index 5b234c1e1..02cb5845e 100644 --- a/src/config/constants.js +++ b/src/config/constants.js @@ -217,6 +217,7 @@ export const EVENT_ROUTE_CHANGE = 'event.route_change' export const ROLE_TOPCODER_USER = 'Topcoder User' export const ROLE_CONNECT_COPILOT = 'Connect Copilot' export const ROLE_CONNECT_MANAGER = 'Connect Manager' +export const ROLE_CONNECT_ADMIN = 'Connect Admin' export const ROLE_ADMINISTRATOR = 'administrator' // FIXME .. remove defaults diff --git a/src/projects/actions/loadProjects.js b/src/projects/actions/loadProjects.js index 441f048e4..7fda7b5cd 100644 --- a/src/projects/actions/loadProjects.js +++ b/src/projects/actions/loadProjects.js @@ -3,7 +3,7 @@ import { PROJECT_SEARCH, GET_PROJECTS, PROJECT_STATUS, PROJECT_STATUS_CANCELLED, SET_SEARCH_TERM, GET_PROJECTS_SEARCH_CRITERIA, CLEAR_PROJECT_SUGGESTIONS_SEARCH, PROJECT_SUGGESTIONS_SEARCH_SUCCESS, - ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER, ROLE_ADMINISTRATOR + ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER, ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN } from '../../config/constants' import { getProjects } from '../../api/projects' import { loadMembers } from '../../actions/members' @@ -23,7 +23,7 @@ const getProjectsWithMembers = (dispatch, getState, criteria, pageNum) => { let isPowerUser = false const loadUser = getState().loadUser // power user roles - const roles = [ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER, ROLE_ADMINISTRATOR] + const roles = [ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER, ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN] if (loadUser.user) { // determine if user is a power user isPowerUser = loadUser.user.roles.some((role) => roles.indexOf(role) !== -1) diff --git a/src/projects/detail/ProjectDetail.jsx b/src/projects/detail/ProjectDetail.jsx index a692ab781..3495c640b 100644 --- a/src/projects/detail/ProjectDetail.jsx +++ b/src/projects/detail/ProjectDetail.jsx @@ -7,7 +7,7 @@ import { renderComponent, branch, compose, withProps } from 'recompose' import { loadProjectDashboard } from '../actions/projectDashboard' import { LOAD_PROJECT_FAILURE, PROJECT_ROLE_CUSTOMER, PROJECT_ROLE_OWNER, - ROLE_ADMINISTRATOR + ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN } from '../../config/constants' import spinnerWhileLoading from '../../components/LoadingSpinner' import CoderBot from '../../components/CoderBot/CoderBot' @@ -71,7 +71,7 @@ class ProjectDetail extends Component { render() { const currentMemberRole = this.getProjectRoleForCurrentUser(this.props) - const powerRoles = [ROLE_ADMINISTRATOR] + const powerRoles = [ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN] const isSuperUser = this.props.currentUserRoles.some((role) => powerRoles.indexOf(role) !== -1) return ( { - const powerUserRoles = [ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER, ROLE_ADMINISTRATOR] - const managerRoles = [ ROLE_ADMINISTRATOR, ROLE_CONNECT_MANAGER ] + const powerUserRoles = [ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER, ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN] + const managerRoles = [ ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN, ROLE_CONNECT_MANAGER ] return { currentUser: { userId: parseInt(loadUser.user.id), diff --git a/src/projects/list/components/Projects/Projects.jsx b/src/projects/list/components/Projects/Projects.jsx index a9b293c23..4b79bd018 100755 --- a/src/projects/list/components/Projects/Projects.jsx +++ b/src/projects/list/components/Projects/Projects.jsx @@ -9,7 +9,12 @@ import ProjectsCardView from './ProjectsCardView' import { loadProjects } from '../../../actions/loadProjects' import _ from 'lodash' import querystring from 'query-string' -import { ROLE_CONNECT_MANAGER, ROLE_CONNECT_COPILOT, ROLE_ADMINISTRATOR } from '../../../../config/constants' +import { + ROLE_CONNECT_MANAGER, + ROLE_CONNECT_COPILOT, + ROLE_ADMINISTRATOR, + ROLE_CONNECT_ADMIN +} from '../../../../config/constants' // This handles showing a spinner while the state is being loaded async import spinnerWhileLoading from '../../../../components/LoadingSpinner' @@ -172,7 +177,7 @@ class Projects extends Component { const mapStateToProps = ({ projectSearch, members, loadUser }) => { let isPowerUser = false - const roles = [ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER, ROLE_ADMINISTRATOR] + const roles = [ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER, ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN] if (loadUser.user) { isPowerUser = loadUser.user.roles.some((role) => roles.indexOf(role) !== -1) } From 98007e6b8a4c4a7e47b1e12234d311c270b40daa Mon Sep 17 00:00:00 2001 From: Vikas Agarwal Date: Wed, 6 Dec 2017 16:29:10 +0530 Subject: [PATCH 2/7] temp deployment for feature branch --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index ecf14c803..b2ff6b005 100644 --- a/circle.yml +++ b/circle.yml @@ -19,7 +19,7 @@ compile: deployment: development: - branch: [dev, 'feature/performance-testing'] + branch: [dev, 'feature/connect-admin-role'] owner: appirio-tech commands: - ./deploy.sh DEV From f54ba5bfdaa8cb4a457db5a6ab4aa3f654adc655 Mon Sep 17 00:00:00 2001 From: Vikas Agarwal Date: Wed, 6 Dec 2017 16:58:59 +0530 Subject: [PATCH 3/7] Instead of deploying each feature branch, deploying one release specific feature branch. --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index b2ff6b005..e99df6d03 100644 --- a/circle.yml +++ b/circle.yml @@ -19,7 +19,7 @@ compile: deployment: development: - branch: [dev, 'feature/connect-admin-role'] + branch: [dev, 'feature/admin-functionality-update-01'] owner: appirio-tech commands: - ./deploy.sh DEV From 280a068d2722865bf6f256e2a250b94821613ef9 Mon Sep 17 00:00:00 2001 From: Vikas Agarwal Date: Wed, 6 Dec 2017 17:36:22 +0530 Subject: [PATCH 4/7] =?UTF-8?q?Github=20issue#1371,=20Admins=20should=20be?= =?UTF-8?q?=20able=20to=20add=20people=20to=20a=20project=20without=20join?= =?UTF-8?q?ing=20=E2=80=94=20Allowed=20admins=20to=20see=20the=20add=20and?= =?UTF-8?q?=20remove=20button=20for=20team=20members=20without=20joining?= =?UTF-8?q?=20the=20project=20=E2=80=94=20It=20works=20fine=20at=20backend?= =?UTF-8?q?=20because=20we=20are=20already=20allowing=20admins=20to=20add/?= =?UTF-8?q?remove=20members=20for=20any=20project.=20And=20we=20just=20add?= =?UTF-8?q?ed=20Connect=20Admin=20role=20to=20the=20list=20of=20admin=20ro?= =?UTF-8?q?les,=20so=20a=20connect=20admin=20is=20also=20able=20to=20add/r?= =?UTF-8?q?emove=20members=20now.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TeamManagement/MemberRow.jsx | 8 ++++---- src/components/TeamManagement/TeamManagement.jsx | 4 ++-- .../detail/containers/TeamManagementContainer.jsx | 2 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/TeamManagement/MemberRow.jsx b/src/components/TeamManagement/MemberRow.jsx index 676747855..dd0d65ced 100644 --- a/src/components/TeamManagement/MemberRow.jsx +++ b/src/components/TeamManagement/MemberRow.jsx @@ -20,7 +20,7 @@ const ActionBtn = (props) => { ) } -const MemberRow = ({ member, currentMember, onMemberDelete, onChangeOwner }) => { +const MemberRow = ({ member, currentMember, currentUser, onMemberDelete, onChangeOwner }) => { let title // rendered member const isOwner = member.isPrimary && member.isCustomer @@ -44,14 +44,14 @@ const MemberRow = ({ member, currentMember, onMemberDelete, onChangeOwner }) => if (!isCurrentOwner && !member.isCopilot) { buttons.push() } - } else if (currentMember) { + } else if (currentMember || currentUser.isAdmin) { // owner can remove only customers - if (isCurrentOwner && member.isCustomer) { + if ((isCurrentOwner && member.isCustomer) || currentUser.isAdmin) { buttons.push() } // manager can remove all except owner - if (currentMember.isManager && !isOwner) { + if (currentMember && currentMember.isManager && !isOwner) { let tooltip = 'Remove team member from project' if (member.isCopilot) { tooltip = 'Remove copilot from project' diff --git a/src/components/TeamManagement/TeamManagement.jsx b/src/components/TeamManagement/TeamManagement.jsx index edc5f62ed..0e129c311 100644 --- a/src/components/TeamManagement/TeamManagement.jsx +++ b/src/components/TeamManagement/TeamManagement.jsx @@ -61,7 +61,7 @@ const TeamManagement = (props) => { return (
- {currentMember && onToggleAddTeamMember(true)}>Add Team Member} + {(currentMember || currentUser.isAdmin) && onToggleAddTeamMember(true)}>Add Team Member} {modalActive &&
} @@ -114,7 +114,7 @@ const TeamManagement = (props) => { })} {canJoin && } - {currentMember && } + {(currentMember || currentUser.isAdmin) && } { showNewMemberConfirmation && } diff --git a/src/projects/detail/containers/TeamManagementContainer.jsx b/src/projects/detail/containers/TeamManagementContainer.jsx index c5265047d..dcf973f65 100644 --- a/src/projects/detail/containers/TeamManagementContainer.jsx +++ b/src/projects/detail/containers/TeamManagementContainer.jsx @@ -222,12 +222,14 @@ class TeamManagementContainer extends Component { } const mapStateToProps = ({ loadUser, members }) => { + const adminRoles = [ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN] const powerUserRoles = [ROLE_CONNECT_COPILOT, ROLE_CONNECT_MANAGER, ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN] const managerRoles = [ ROLE_ADMINISTRATOR, ROLE_CONNECT_ADMIN, ROLE_CONNECT_MANAGER ] return { currentUser: { userId: parseInt(loadUser.user.id), isCopilot: _.indexOf(loadUser.user.roles, ROLE_CONNECT_COPILOT) > -1, + isAdmin: _.intersection(loadUser.user.roles, adminRoles).length > 0, isManager: loadUser.user.roles.some((role) => managerRoles.indexOf(role) !== -1), isCustomer: !loadUser.user.roles.some((role) => powerUserRoles.indexOf(role) !== -1) }, From d8c0dfb1d30e375488e003a594fade84b5a91ef5 Mon Sep 17 00:00:00 2001 From: Vikas Agarwal Date: Tue, 12 Dec 2017 17:54:39 +0530 Subject: [PATCH 5/7] Fixed duplicate remove buttons for managers https://github.com/appirio-tech/connect-app/issues/1243#issuecomment-351029926 --- src/components/TeamManagement/MemberRow.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/TeamManagement/MemberRow.jsx b/src/components/TeamManagement/MemberRow.jsx index dd0d65ced..c0965cb6b 100644 --- a/src/components/TeamManagement/MemberRow.jsx +++ b/src/components/TeamManagement/MemberRow.jsx @@ -46,12 +46,12 @@ const MemberRow = ({ member, currentMember, currentUser, onMemberDelete, onChang } } else if (currentMember || currentUser.isAdmin) { // owner can remove only customers - if ((isCurrentOwner && member.isCustomer) || currentUser.isAdmin) { + if (isCurrentOwner && member.isCustomer) { buttons.push() } // manager can remove all except owner - if (currentMember && currentMember.isManager && !isOwner) { + if (currentMember && (currentMember.isManager || currentUser.isAdmin) && !isOwner) { let tooltip = 'Remove team member from project' if (member.isCopilot) { tooltip = 'Remove copilot from project' From 33b146c5ce809b41909780ee6afddc53a84bb33f Mon Sep 17 00:00:00 2001 From: Vikas Agarwal Date: Thu, 14 Dec 2017 17:19:29 +0530 Subject: [PATCH 6/7] =?UTF-8?q?Github=20issue#1371,=20Admins=20should=20be?= =?UTF-8?q?=20able=20to=20add=20people=20to=20a=20project=20without=20join?= =?UTF-8?q?ing=20=E2=80=94=20Allowed=20admins/managers=20to=20remove=20own?= =?UTF-8?q?ers/customers=20as=20well.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/TeamManagement/MemberRow.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/TeamManagement/MemberRow.jsx b/src/components/TeamManagement/MemberRow.jsx index c0965cb6b..992c8bdb1 100644 --- a/src/components/TeamManagement/MemberRow.jsx +++ b/src/components/TeamManagement/MemberRow.jsx @@ -51,7 +51,7 @@ const MemberRow = ({ member, currentMember, currentUser, onMemberDelete, onChang } // manager can remove all except owner - if (currentMember && (currentMember.isManager || currentUser.isAdmin) && !isOwner) { + if ((currentMember && currentMember.isManager) || currentUser.isAdmin) { let tooltip = 'Remove team member from project' if (member.isCopilot) { tooltip = 'Remove copilot from project' @@ -59,6 +59,9 @@ const MemberRow = ({ member, currentMember, currentUser, onMemberDelete, onChang if (member.isManager) { tooltip = 'Remove manager from project' } + if (member.isCustomer && isOwner) { + tooltip = 'Remove owner from project' + } buttons.push() } From 1bc5e36a41678aded13599d68eb2ca80acfc832f Mon Sep 17 00:00:00 2001 From: Vikas Agarwal Date: Wed, 20 Dec 2017 17:02:38 +0530 Subject: [PATCH 7/7] Removing feature branch from the deployable branch list. --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index e99df6d03..2084eb9ca 100644 --- a/circle.yml +++ b/circle.yml @@ -19,7 +19,7 @@ compile: deployment: development: - branch: [dev, 'feature/admin-functionality-update-01'] + branch: dev owner: appirio-tech commands: - ./deploy.sh DEV