瀏覽代碼

display team member labels

Marcus Efraimsson 7 年之前
父節點
當前提交
da68b858d7

+ 10 - 0
public/app/features/teams/TeamMembers.test.tsx

@@ -12,6 +12,7 @@ const setup = (propOverrides?: object) => {
     loadTeamMembers: jest.fn(),
     loadTeamMembers: jest.fn(),
     addTeamMember: jest.fn(),
     addTeamMember: jest.fn(),
     removeTeamMember: jest.fn(),
     removeTeamMember: jest.fn(),
+    syncEnabled: false,
   };
   };
 
 
   Object.assign(props, propOverrides);
   Object.assign(props, propOverrides);
@@ -39,6 +40,15 @@ describe('Render', () => {
 
 
     expect(wrapper).toMatchSnapshot();
     expect(wrapper).toMatchSnapshot();
   });
   });
+
+  it('should render team members when sync enabled', () => {
+    const { wrapper } = setup({
+      members: getMockTeamMembers(5),
+      syncEnabled: true,
+    });
+
+    expect(wrapper).toMatchSnapshot();
+  });
 });
 });
 
 
 describe('Functions', () => {
 describe('Functions', () => {

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

@@ -3,6 +3,7 @@ import { connect } from 'react-redux';
 import SlideDown from 'app/core/components/Animations/SlideDown';
 import SlideDown from 'app/core/components/Animations/SlideDown';
 import { UserPicker, User } from 'app/core/components/Picker/UserPicker';
 import { UserPicker, User } from 'app/core/components/Picker/UserPicker';
 import DeleteButton from 'app/core/components/DeleteButton/DeleteButton';
 import DeleteButton from 'app/core/components/DeleteButton/DeleteButton';
+import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
 import { TeamMember } from '../../types';
 import { TeamMember } from '../../types';
 import { loadTeamMembers, addTeamMember, removeTeamMember, setSearchMemberQuery } from './state/actions';
 import { loadTeamMembers, addTeamMember, removeTeamMember, setSearchMemberQuery } from './state/actions';
 import { getSearchMemberQuery, getTeamMembers } from './state/selectors';
 import { getSearchMemberQuery, getTeamMembers } from './state/selectors';
@@ -14,6 +15,7 @@ export interface Props {
   addTeamMember: typeof addTeamMember;
   addTeamMember: typeof addTeamMember;
   removeTeamMember: typeof removeTeamMember;
   removeTeamMember: typeof removeTeamMember;
   setSearchMemberQuery: typeof setSearchMemberQuery;
   setSearchMemberQuery: typeof setSearchMemberQuery;
+  syncEnabled: boolean;
 }
 }
 
 
 export interface State {
 export interface State {
@@ -52,7 +54,19 @@ export class TeamMembers extends PureComponent<Props, State> {
     this.setState({ newTeamMember: null });
     this.setState({ newTeamMember: null });
   };
   };
 
 
-  renderMember(member: TeamMember) {
+  renderLabels(labels: string[]) {
+    if (!labels) {
+      return <td />;
+    }
+
+    return (
+      <td>
+        {labels.map(label => <TagBadge key={label} label={label} removeIcon={false} count={0} onClick={() => {}} />)}
+      </td>
+    );
+  }
+
+  renderMember(member: TeamMember, syncEnabled: boolean) {
     return (
     return (
       <tr key={member.userId}>
       <tr key={member.userId}>
         <td className="width-4 text-center">
         <td className="width-4 text-center">
@@ -60,6 +74,7 @@ export class TeamMembers extends PureComponent<Props, State> {
         </td>
         </td>
         <td>{member.login}</td>
         <td>{member.login}</td>
         <td>{member.email}</td>
         <td>{member.email}</td>
+        {syncEnabled ? this.renderLabels(member.labels) : ''}
         <td className="text-right">
         <td className="text-right">
           <DeleteButton onConfirmDelete={() => this.onRemoveMember(member)} />
           <DeleteButton onConfirmDelete={() => this.onRemoveMember(member)} />
         </td>
         </td>
@@ -69,7 +84,7 @@ export class TeamMembers extends PureComponent<Props, State> {
 
 
   render() {
   render() {
     const { newTeamMember, isAdding } = this.state;
     const { newTeamMember, isAdding } = this.state;
-    const { searchMemberQuery, members } = this.props;
+    const { searchMemberQuery, members, syncEnabled } = this.props;
     const newTeamMemberValue = newTeamMember && newTeamMember.id.toString();
     const newTeamMemberValue = newTeamMember && newTeamMember.id.toString();
 
 
     return (
     return (
@@ -120,10 +135,11 @@ export class TeamMembers extends PureComponent<Props, State> {
                 <th />
                 <th />
                 <th>Name</th>
                 <th>Name</th>
                 <th>Email</th>
                 <th>Email</th>
+                {syncEnabled ? <th /> : ''}
                 <th style={{ width: '1%' }} />
                 <th style={{ width: '1%' }} />
               </tr>
               </tr>
             </thead>
             </thead>
-            <tbody>{members && members.map(member => this.renderMember(member))}</tbody>
+            <tbody>{members && members.map(member => this.renderMember(member, syncEnabled))}</tbody>
           </table>
           </table>
         </div>
         </div>
       </div>
       </div>

+ 1 - 1
public/app/features/teams/TeamPages.tsx

@@ -63,7 +63,7 @@ export class TeamPages extends PureComponent<Props, State> {
 
 
     switch (currentPage) {
     switch (currentPage) {
       case PageTypes.Members:
       case PageTypes.Members:
-        return <TeamMembers />;
+        return <TeamMembers syncEnabled={isSyncEnabled} />;
 
 
       case PageTypes.Settings:
       case PageTypes.Settings:
         return <TeamSettings />;
         return <TeamSettings />;

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

@@ -35,6 +35,7 @@ export const getMockTeamMembers = (amount: number): TeamMember[] => {
       avatarUrl: 'some/url/',
       avatarUrl: 'some/url/',
       email: 'test@test.com',
       email: 'test@test.com',
       login: `testUser-${i}`,
       login: `testUser-${i}`,
+      labels: ['label 1', 'label 2'],
     });
     });
   }
   }
 
 
@@ -48,6 +49,7 @@ export const getMockTeamMember = (): TeamMember => {
     avatarUrl: 'some/url/',
     avatarUrl: 'some/url/',
     email: 'test@test.com',
     email: 'test@test.com',
     login: 'testUser',
     login: 'testUser',
+    labels: [],
   };
   };
 };
 };
 
 

+ 302 - 0
public/app/features/teams/__snapshots__/TeamMembers.test.tsx.snap

@@ -315,3 +315,305 @@ exports[`Render should render team members 1`] = `
   </div>
   </div>
 </div>
 </div>
 `;
 `;
+
+exports[`Render should render team members when sync enabled 1`] = `
+<div>
+  <div
+    className="page-action-bar"
+  >
+    <div
+      className="gf-form gf-form--grow"
+    >
+      <label
+        className="gf-form--has-input-icon gf-form--grow"
+      >
+        <input
+          className="gf-form-input"
+          onChange={[Function]}
+          placeholder="Search members"
+          type="text"
+          value=""
+        />
+        <i
+          className="gf-form-input-icon fa fa-search"
+        />
+      </label>
+    </div>
+    <div
+      className="page-action-bar__spacer"
+    />
+    <button
+      className="btn btn-success pull-right"
+      disabled={false}
+      onClick={[Function]}
+    >
+      <i
+        className="fa fa-plus"
+      />
+       Add a member
+    </button>
+  </div>
+  <Component
+    in={false}
+  >
+    <div
+      className="cta-form"
+    >
+      <button
+        className="cta-form__close btn btn-transparent"
+        onClick={[Function]}
+      >
+        <i
+          className="fa fa-close"
+        />
+      </button>
+      <h5>
+        Add Team Member
+      </h5>
+      <div
+        className="gf-form-inline"
+      >
+        <UserPicker
+          className="width-30"
+          onSelected={[Function]}
+          value={null}
+        />
+      </div>
+    </div>
+  </Component>
+  <div
+    className="admin-list-table"
+  >
+    <table
+      className="filter-table filter-table--hover form-inline"
+    >
+      <thead>
+        <tr>
+          <th />
+          <th>
+            Name
+          </th>
+          <th>
+            Email
+          </th>
+          <th />
+          <th
+            style={
+              Object {
+                "width": "1%",
+              }
+            }
+          />
+        </tr>
+      </thead>
+      <tbody>
+        <tr
+          key="1"
+        >
+          <td
+            className="width-4 text-center"
+          >
+            <img
+              className="filter-table__avatar"
+              src="some/url/"
+            />
+          </td>
+          <td>
+            testUser-1
+          </td>
+          <td>
+            test@test.com
+          </td>
+          <td>
+            <TagBadge
+              count={0}
+              key="label 1"
+              label="label 1"
+              onClick={[Function]}
+              removeIcon={false}
+            />
+            <TagBadge
+              count={0}
+              key="label 2"
+              label="label 2"
+              onClick={[Function]}
+              removeIcon={false}
+            />
+          </td>
+          <td
+            className="text-right"
+          >
+            <DeleteButton
+              onConfirmDelete={[Function]}
+            />
+          </td>
+        </tr>
+        <tr
+          key="2"
+        >
+          <td
+            className="width-4 text-center"
+          >
+            <img
+              className="filter-table__avatar"
+              src="some/url/"
+            />
+          </td>
+          <td>
+            testUser-2
+          </td>
+          <td>
+            test@test.com
+          </td>
+          <td>
+            <TagBadge
+              count={0}
+              key="label 1"
+              label="label 1"
+              onClick={[Function]}
+              removeIcon={false}
+            />
+            <TagBadge
+              count={0}
+              key="label 2"
+              label="label 2"
+              onClick={[Function]}
+              removeIcon={false}
+            />
+          </td>
+          <td
+            className="text-right"
+          >
+            <DeleteButton
+              onConfirmDelete={[Function]}
+            />
+          </td>
+        </tr>
+        <tr
+          key="3"
+        >
+          <td
+            className="width-4 text-center"
+          >
+            <img
+              className="filter-table__avatar"
+              src="some/url/"
+            />
+          </td>
+          <td>
+            testUser-3
+          </td>
+          <td>
+            test@test.com
+          </td>
+          <td>
+            <TagBadge
+              count={0}
+              key="label 1"
+              label="label 1"
+              onClick={[Function]}
+              removeIcon={false}
+            />
+            <TagBadge
+              count={0}
+              key="label 2"
+              label="label 2"
+              onClick={[Function]}
+              removeIcon={false}
+            />
+          </td>
+          <td
+            className="text-right"
+          >
+            <DeleteButton
+              onConfirmDelete={[Function]}
+            />
+          </td>
+        </tr>
+        <tr
+          key="4"
+        >
+          <td
+            className="width-4 text-center"
+          >
+            <img
+              className="filter-table__avatar"
+              src="some/url/"
+            />
+          </td>
+          <td>
+            testUser-4
+          </td>
+          <td>
+            test@test.com
+          </td>
+          <td>
+            <TagBadge
+              count={0}
+              key="label 1"
+              label="label 1"
+              onClick={[Function]}
+              removeIcon={false}
+            />
+            <TagBadge
+              count={0}
+              key="label 2"
+              label="label 2"
+              onClick={[Function]}
+              removeIcon={false}
+            />
+          </td>
+          <td
+            className="text-right"
+          >
+            <DeleteButton
+              onConfirmDelete={[Function]}
+            />
+          </td>
+        </tr>
+        <tr
+          key="5"
+        >
+          <td
+            className="width-4 text-center"
+          >
+            <img
+              className="filter-table__avatar"
+              src="some/url/"
+            />
+          </td>
+          <td>
+            testUser-5
+          </td>
+          <td>
+            test@test.com
+          </td>
+          <td>
+            <TagBadge
+              count={0}
+              key="label 1"
+              label="label 1"
+              onClick={[Function]}
+              removeIcon={false}
+            />
+            <TagBadge
+              count={0}
+              key="label 2"
+              label="label 2"
+              onClick={[Function]}
+              removeIcon={false}
+            />
+          </td>
+          <td
+            className="text-right"
+          >
+            <DeleteButton
+              onConfirmDelete={[Function]}
+            />
+          </td>
+        </tr>
+      </tbody>
+    </table>
+  </div>
+</div>
+`;

+ 3 - 1
public/app/features/teams/__snapshots__/TeamPages.test.tsx.snap

@@ -29,7 +29,9 @@ exports[`Render should render member page if team not empty 1`] = `
   <div
   <div
     className="page-container page-body"
     className="page-container page-body"
   >
   >
-    <Connect(TeamMembers) />
+    <Connect(TeamMembers)
+      syncEnabled={true}
+    />
   </div>
   </div>
 </div>
 </div>
 `;
 `;

+ 1 - 0
public/app/types/teams.ts

@@ -12,6 +12,7 @@ export interface TeamMember {
   avatarUrl: string;
   avatarUrl: string;
   email: string;
   email: string;
   login: string;
   login: string;
+  labels: string[];
 }
 }
 
 
 export interface TeamGroup {
 export interface TeamGroup {