Просмотр исходного кода

teams: disable buttons for team members

Hugo Häggmark 6 лет назад
Родитель
Сommit
b82b94a247

+ 11 - 13
packages/grafana-ui/src/components/DeleteButton/DeleteButton.tsx

@@ -2,6 +2,7 @@ import React, { PureComponent, SyntheticEvent } from 'react';
 
 interface Props {
   onConfirm(): void;
+  disabled?: boolean;
 }
 
 interface State {
@@ -33,25 +34,22 @@ export class DeleteButton extends PureComponent<Props, State> {
   };
 
   render() {
-    const { onConfirm } = this.props;
-    let showConfirm;
-    let showDeleteButton;
-
-    if (this.state.showConfirm) {
-      showConfirm = 'show';
-      showDeleteButton = 'hide';
-    } else {
-      showConfirm = 'hide';
-      showDeleteButton = 'show';
-    }
+    const { onConfirm, disabled } = this.props;
+    const showConfirmClass = this.state.showConfirm ? 'show' : 'hide';
+    const showDeleteButtonClass = this.state.showConfirm ? 'hide' : 'show';
+    const disabledClass = disabled ? 'disabled btn-inverse' : '';
+    const onClick = disabled ? () => {} : this.onClickDelete;
 
     return (
       <span className="delete-button-container">
-        <a className={'delete-button ' + showDeleteButton + ' btn btn-danger btn-small'} onClick={this.onClickDelete}>
+        <a
+          className={`delete-button ${showDeleteButtonClass} btn btn-danger btn-small ${disabledClass}`}
+          onClick={onClick}
+        >
           <i className="fa fa-remove" />
         </a>
         <span className="confirm-delete-container">
-          <span className={'confirm-delete ' + showConfirm}>
+          <span className={`confirm-delete ${showConfirmClass}`}>
             <a className="btn btn-small" onClick={this.onClickCancel}>
               Cancel
             </a>

+ 23 - 11
public/app/features/teams/TeamMembers.test.tsx

@@ -6,16 +6,17 @@ import { getMockTeamMember, getMockTeamMembers } from './__mocks__/teamMocks';
 import { SelectOptionItem } from '@grafana/ui';
 import { contextSrv } from 'app/core/services/context_srv';
 
+const signedInUserId = 1;
+const originalContextSrv = contextSrv;
+
 jest.mock('app/core/services/context_srv', () => ({
   contextSrv: {
     isGrafanaAdmin: false,
     hasRole: role => false,
-    user: { id: 1 },
+    user: { id: signedInUserId },
   },
 }));
 
-const originalContextSrv = contextSrv;
-
 interface SetupProps {
   propOverrides?: object;
   isGrafanaAdmin?: boolean;
@@ -64,7 +65,7 @@ describe('Render', () => {
   it('should render team members', () => {
     const { wrapper } = setup({
       propOverrides: {
-        members: getMockTeamMembers(5),
+        members: getMockTeamMembers(5, 5),
       },
     });
 
@@ -74,7 +75,7 @@ describe('Render', () => {
   it('should render team members when sync enabled', () => {
     const { wrapper } = setup({
       propOverrides: {
-        members: getMockTeamMembers(5),
+        members: getMockTeamMembers(5, 5),
         syncEnabled: true,
       },
     });
@@ -84,8 +85,7 @@ describe('Render', () => {
 
   describe('when feature toggle editorsCanAdmin is turned on', () => {
     it('should render permissions select if user is Grafana Admin', () => {
-      const members = getMockTeamMembers(5);
-      members[4].permission = TeamPermissionLevel.Admin;
+      const members = getMockTeamMembers(5, 5);
       const { wrapper } = setup({
         propOverrides: { members, editorsCanAdmin: true },
         isGrafanaAdmin: true,
@@ -96,8 +96,7 @@ describe('Render', () => {
     });
 
     it('should render permissions select if user is Org Admin', () => {
-      const members = getMockTeamMembers(5);
-      members[4].permission = TeamPermissionLevel.Admin;
+      const members = getMockTeamMembers(5, 5);
       const { wrapper } = setup({
         propOverrides: { members, editorsCanAdmin: true },
         isGrafanaAdmin: false,
@@ -108,8 +107,7 @@ describe('Render', () => {
     });
 
     it('should render permissions select if user is team admin', () => {
-      const members = getMockTeamMembers(5);
-      members[0].permission = TeamPermissionLevel.Admin;
+      const members = getMockTeamMembers(5, signedInUserId);
       const { wrapper } = setup({
         propOverrides: { members, editorsCanAdmin: true },
         isGrafanaAdmin: false,
@@ -118,6 +116,20 @@ describe('Render', () => {
 
       expect(wrapper).toMatchSnapshot();
     });
+
+    it('should render span and disable buttons if user is team member', () => {
+      const members = getMockTeamMembers(5, 5);
+      const { wrapper } = setup({
+        propOverrides: {
+          members,
+          editorsCanAdmin: true,
+        },
+        isGrafanaAdmin: false,
+        isOrgAdmin: false,
+      });
+
+      expect(wrapper).toMatchSnapshot();
+    });
   });
 });
 

+ 19 - 9
public/app/features/teams/TeamMembers.tsx

@@ -39,7 +39,7 @@ export class TeamMembers extends PureComponent<Props, State> {
   constructor(props) {
     super(props);
     this.state = { isAdding: false, newTeamMember: null };
-    this.renderPermissionsSelect = this.renderPermissionsSelect.bind(this);
+    this.renderPermissions = this.renderPermissions.bind(this);
   }
 
   componentDidMount() {
@@ -88,13 +88,19 @@ export class TeamMembers extends PureComponent<Props, State> {
     this.props.updateTeamMember(updatedTeamMember);
   };
 
-  renderPermissionsSelect(member: TeamMember) {
+  private isSignedInUserTeamAdmin = () => {
     const { members, editorsCanAdmin } = this.props;
     const userInMembers = members.find(m => m.userId === contextSrv.user.id);
-    const isUserTeamAdmin =
-      contextSrv.isGrafanaAdmin || contextSrv.hasRole(OrgRole.Admin)
-        ? true
-        : userInMembers && userInMembers.permission === TeamPermissionLevel.Admin;
+    const isAdmin = contextSrv.isGrafanaAdmin || contextSrv.hasRole(OrgRole.Admin);
+    const userIsTeamAdmin = userInMembers && userInMembers.permission === TeamPermissionLevel.Admin;
+    const isSignedInUserTeamAdmin = isAdmin || userIsTeamAdmin;
+
+    return isSignedInUserTeamAdmin || !editorsCanAdmin;
+  };
+
+  renderPermissions(member: TeamMember) {
+    const { editorsCanAdmin } = this.props;
+    const isUserTeamAdmin = this.isSignedInUserTeamAdmin();
     const value = teamsPermissionLevels.find(dp => dp.value === member.permission);
 
     return (
@@ -125,10 +131,10 @@ export class TeamMembers extends PureComponent<Props, State> {
         </td>
         <td>{member.login}</td>
         <td>{member.email}</td>
-        {this.renderPermissionsSelect(member)}
+        {this.renderPermissions(member)}
         {syncEnabled && this.renderLabels(member.labels)}
         <td className="text-right">
-          <DeleteButton onConfirm={() => this.onRemoveMember(member)} />
+          <DeleteButton onConfirm={() => this.onRemoveMember(member)} disabled={!this.isSignedInUserTeamAdmin()} />
         </td>
       </tr>
     );
@@ -152,7 +158,11 @@ export class TeamMembers extends PureComponent<Props, State> {
 
           <div className="page-action-bar__spacer" />
 
-          <button className="btn btn-primary pull-right" onClick={this.onToggleAdding} disabled={isAdding}>
+          <button
+            className="btn btn-primary pull-right"
+            onClick={this.onToggleAdding}
+            disabled={isAdding || !this.isSignedInUserTeamAdmin()}
+          >
             Add member
           </button>
         </div>

+ 2 - 2
public/app/features/teams/__mocks__/teamMocks.ts

@@ -25,7 +25,7 @@ export const getMockTeam = (): Team => {
   };
 };
 
-export const getMockTeamMembers = (amount: number): TeamMember[] => {
+export const getMockTeamMembers = (amount: number, teamAdminId: number): TeamMember[] => {
   const teamMembers: TeamMember[] = [];
 
   for (let i = 1; i <= amount; i++) {
@@ -36,7 +36,7 @@ export const getMockTeamMembers = (amount: number): TeamMember[] => {
       email: 'test@test.com',
       login: `testUser-${i}`,
       labels: ['label 1', 'label 2'],
-      permission: TeamPermissionLevel.Member,
+      permission: i === teamAdminId ? TeamPermissionLevel.Admin : TeamPermissionLevel.Member,
     });
   }
 

Разница между файлами не показана из-за своего большого размера
+ 702 - 231
public/app/features/teams/__snapshots__/TeamMembers.test.tsx.snap


+ 1 - 1
public/app/features/teams/state/selectors.test.ts

@@ -40,7 +40,7 @@ describe('Team selectors', () => {
   });
 
   describe('Get members', () => {
-    const mockTeamMembers = getMockTeamMembers(5);
+    const mockTeamMembers = getMockTeamMembers(5, 5);
 
     it('should return team members', () => {
       const mockState: TeamState = {

Некоторые файлы не были показаны из-за большого количества измененных файлов