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

teams: disable new team button if user is viewer

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

+ 43 - 1
public/app/features/teams/TeamList.test.tsx

@@ -1,8 +1,9 @@
 import React from 'react';
 import { shallow } from 'enzyme';
 import { Props, TeamList } from './TeamList';
-import { NavModel, Team } from '../../types';
+import { NavModel, Team, OrgRole } from '../../types';
 import { getMockTeam, getMultipleMockTeams } from './__mocks__/teamMocks';
+import { User } from 'app/core/services/context_srv';
 
 const setup = (propOverrides?: object) => {
   const props: Props = {
@@ -21,6 +22,11 @@ const setup = (propOverrides?: object) => {
     searchQuery: '',
     teamsCount: 0,
     hasFetched: false,
+    editorsCanAdmin: false,
+    signedInUser: {
+      id: 1,
+      orgRole: OrgRole.Viewer,
+    } as User,
   };
 
   Object.assign(props, propOverrides);
@@ -49,6 +55,42 @@ describe('Render', () => {
 
     expect(wrapper).toMatchSnapshot();
   });
+
+  describe('when feature toggle editorsCanAdmin is turned on', () => {
+    describe('and signedin user is not viewer', () => {
+      it('should enable the new team button', () => {
+        const { wrapper } = setup({
+          teams: getMultipleMockTeams(1),
+          teamsCount: 1,
+          hasFetched: true,
+          editorsCanAdmin: true,
+          signedInUser: {
+            id: 1,
+            orgRole: OrgRole.Editor,
+          } as User,
+        });
+
+        expect(wrapper).toMatchSnapshot();
+      });
+    });
+
+    describe('and signedin user is a viewer', () => {
+      it('should disable the new team button', () => {
+        const { wrapper } = setup({
+          teams: getMultipleMockTeams(1),
+          teamsCount: 1,
+          hasFetched: true,
+          editorsCanAdmin: true,
+          signedInUser: {
+            id: 1,
+            orgRole: OrgRole.Viewer,
+          } as User,
+        });
+
+        expect(wrapper).toMatchSnapshot();
+      });
+    });
+  });
 });
 
 describe('Life cycle', () => {

+ 10 - 3
public/app/features/teams/TeamList.tsx

@@ -4,11 +4,13 @@ import { hot } from 'react-hot-loader';
 import Page from 'app/core/components/Page/Page';
 import { DeleteButton } from '@grafana/ui';
 import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
-import { NavModel, Team } from 'app/types';
+import { NavModel, Team, OrgRole } from 'app/types';
 import { loadTeams, deleteTeam, setSearchQuery } from './state/actions';
 import { getSearchQuery, getTeams, getTeamsCount } from './state/selectors';
 import { getNavModel } from 'app/core/selectors/navModel';
 import { FilterInput } from 'app/core/components/FilterInput/FilterInput';
+import { config } from 'app/core/config';
+import { contextSrv, User } from 'app/core/services/context_srv';
 
 export interface Props {
   navModel: NavModel;
@@ -19,6 +21,8 @@ export interface Props {
   loadTeams: typeof loadTeams;
   deleteTeam: typeof deleteTeam;
   setSearchQuery: typeof setSearchQuery;
+  editorsCanAdmin?: boolean;
+  signedInUser?: User;
 }
 
 export class TeamList extends PureComponent<Props, any> {
@@ -84,7 +88,8 @@ export class TeamList extends PureComponent<Props, any> {
   }
 
   renderTeamList() {
-    const { teams, searchQuery } = this.props;
+    const { teams, searchQuery, editorsCanAdmin, signedInUser } = this.props;
+    const disabledClass = editorsCanAdmin && signedInUser.orgRole === OrgRole.Viewer ? ' disabled' : '';
 
     return (
       <>
@@ -101,7 +106,7 @@ export class TeamList extends PureComponent<Props, any> {
 
           <div className="page-action-bar__spacer" />
 
-          <a className="btn btn-primary" href="org/teams/new">
+          <a className={`btn btn-primary${disabledClass}`} href="org/teams/new">
             New team
           </a>
         </div>
@@ -152,6 +157,8 @@ function mapStateToProps(state) {
     searchQuery: getSearchQuery(state.teams),
     teamsCount: getTeamsCount(state.teams),
     hasFetched: state.teams.hasFetched,
+    editorsCanAdmin: config.editorsCanAdmin, // this makes the feature toggle mockable/controllable from tests,
+    signedInUser: contextSrv.user, // this makes the feature toggle mockable/controllable from tests,
   };
 }
 

+ 250 - 0
public/app/features/teams/__snapshots__/TeamList.test.tsx.snap

@@ -343,3 +343,253 @@ exports[`Render should render teams table 1`] = `
   </PageContents>
 </Page>
 `;
+
+exports[`Render when feature toggle editorsCanAdmin is turned on and signedin user is a viewer should disable the new team button 1`] = `
+<Page
+  navModel={
+    Object {
+      "main": Object {
+        "text": "Configuration",
+      },
+      "node": Object {
+        "text": "Team List",
+      },
+    }
+  }
+>
+  <PageContents
+    isLoading={false}
+  >
+    <div
+      className="page-action-bar"
+    >
+      <div
+        className="gf-form gf-form--grow"
+      >
+        <ForwardRef
+          inputClassName="gf-form-input"
+          labelClassName="gf-form--has-input-icon gf-form--grow"
+          onChange={[Function]}
+          placeholder="Search teams"
+          value=""
+        />
+      </div>
+      <div
+        className="page-action-bar__spacer"
+      />
+      <a
+        className="btn btn-primary disabled"
+        href="org/teams/new"
+      >
+        New team
+      </a>
+    </div>
+    <div
+      className="admin-list-table"
+    >
+      <table
+        className="filter-table filter-table--hover form-inline"
+      >
+        <thead>
+          <tr>
+            <th />
+            <th>
+              Name
+            </th>
+            <th>
+              Email
+            </th>
+            <th>
+              Members
+            </th>
+            <th
+              style={
+                Object {
+                  "width": "1%",
+                }
+              }
+            />
+          </tr>
+        </thead>
+        <tbody>
+          <tr
+            key="1"
+          >
+            <td
+              className="width-4 text-center link-td"
+            >
+              <a
+                href="org/teams/edit/1"
+              >
+                <img
+                  className="filter-table__avatar"
+                  src="some/url/"
+                />
+              </a>
+            </td>
+            <td
+              className="link-td"
+            >
+              <a
+                href="org/teams/edit/1"
+              >
+                test-1
+              </a>
+            </td>
+            <td
+              className="link-td"
+            >
+              <a
+                href="org/teams/edit/1"
+              >
+                test-1@test.com
+              </a>
+            </td>
+            <td
+              className="link-td"
+            >
+              <a
+                href="org/teams/edit/1"
+              >
+                1
+              </a>
+            </td>
+            <td
+              className="text-right"
+            >
+              <DeleteButton
+                onConfirm={[Function]}
+              />
+            </td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+  </PageContents>
+</Page>
+`;
+
+exports[`Render when feature toggle editorsCanAdmin is turned on and signedin user is not viewer should enable the new team button 1`] = `
+<Page
+  navModel={
+    Object {
+      "main": Object {
+        "text": "Configuration",
+      },
+      "node": Object {
+        "text": "Team List",
+      },
+    }
+  }
+>
+  <PageContents
+    isLoading={false}
+  >
+    <div
+      className="page-action-bar"
+    >
+      <div
+        className="gf-form gf-form--grow"
+      >
+        <ForwardRef
+          inputClassName="gf-form-input"
+          labelClassName="gf-form--has-input-icon gf-form--grow"
+          onChange={[Function]}
+          placeholder="Search teams"
+          value=""
+        />
+      </div>
+      <div
+        className="page-action-bar__spacer"
+      />
+      <a
+        className="btn btn-primary"
+        href="org/teams/new"
+      >
+        New team
+      </a>
+    </div>
+    <div
+      className="admin-list-table"
+    >
+      <table
+        className="filter-table filter-table--hover form-inline"
+      >
+        <thead>
+          <tr>
+            <th />
+            <th>
+              Name
+            </th>
+            <th>
+              Email
+            </th>
+            <th>
+              Members
+            </th>
+            <th
+              style={
+                Object {
+                  "width": "1%",
+                }
+              }
+            />
+          </tr>
+        </thead>
+        <tbody>
+          <tr
+            key="1"
+          >
+            <td
+              className="width-4 text-center link-td"
+            >
+              <a
+                href="org/teams/edit/1"
+              >
+                <img
+                  className="filter-table__avatar"
+                  src="some/url/"
+                />
+              </a>
+            </td>
+            <td
+              className="link-td"
+            >
+              <a
+                href="org/teams/edit/1"
+              >
+                test-1
+              </a>
+            </td>
+            <td
+              className="link-td"
+            >
+              <a
+                href="org/teams/edit/1"
+              >
+                test-1@test.com
+              </a>
+            </td>
+            <td
+              className="link-td"
+            >
+              <a
+                href="org/teams/edit/1"
+              >
+                1
+              </a>
+            </td>
+            <td
+              className="text-right"
+            >
+              <DeleteButton
+                onConfirm={[Function]}
+              />
+            </td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+  </PageContents>
+</Page>
+`;