Peter Holmberg 7 vuotta sitten
vanhempi
commit
a188ceacbc

+ 0 - 1
public/app/core/components/OrgActionBar/OrgActionBar.test.tsx

@@ -5,7 +5,6 @@ import OrgActionBar, { Props } from './OrgActionBar';
 const setup = (propOverrides?: object) => {
 const setup = (propOverrides?: object) => {
   const props: Props = {
   const props: Props = {
     searchQuery: '',
     searchQuery: '',
-    showLayoutMode: true,
     setSearchQuery: jest.fn(),
     setSearchQuery: jest.fn(),
     linkButton: { href: 'some/url', title: 'test' },
     linkButton: { href: 'some/url', title: 'test' },
   };
   };

+ 32 - 0
public/app/features/users/InviteesTable.test.tsx

@@ -0,0 +1,32 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import InviteesTable, { Props } from './InviteesTable';
+import { Invitee } from 'app/types';
+import { getMockInvitees } from './__mocks__/userMocks';
+
+const setup = (propOverrides?: object) => {
+  const props: Props = {
+    invitees: [] as Invitee[],
+    revokeInvite: jest.fn(),
+  };
+
+  Object.assign(props, propOverrides);
+
+  return shallow(<InviteesTable {...props} />);
+};
+
+describe('Render', () => {
+  it('should render component', () => {
+    const wrapper = setup();
+
+    expect(wrapper).toMatchSnapshot();
+  });
+
+  it('should render invitees', () => {
+    const wrapper = setup({
+      invitees: getMockInvitees(5),
+    });
+
+    expect(wrapper).toMatchSnapshot();
+  });
+});

+ 8 - 3
public/app/features/users/InviteesTable.tsx

@@ -7,10 +7,10 @@ export interface Props {
 }
 }
 
 
 export default class InviteesTable extends PureComponent<Props> {
 export default class InviteesTable extends PureComponent<Props> {
-  private copyRef = createRef<HTMLTextAreaElement>();
+  private copyUrlRef = createRef<HTMLTextAreaElement>();
 
 
   copyToClipboard = () => {
   copyToClipboard = () => {
-    const node = this.copyRef.current;
+    const node = this.copyUrlRef.current;
 
 
     if (node) {
     if (node) {
       node.select();
       node.select();
@@ -39,7 +39,12 @@ export default class InviteesTable extends PureComponent<Props> {
                 <td>{invitee.name}</td>
                 <td>{invitee.name}</td>
                 <td className="text-right">
                 <td className="text-right">
                   <button className="btn btn-inverse btn-mini" onClick={this.copyToClipboard}>
                   <button className="btn btn-inverse btn-mini" onClick={this.copyToClipboard}>
-                    <textarea readOnly={true} value={invitee.url} style={{ display: 'none' }} ref={this.copyRef} />
+                    <textarea
+                      readOnly={true}
+                      value={invitee.url}
+                      style={{ position: 'absolute', right: -1000 }}
+                      ref={this.copyUrlRef}
+                    />
                     <i className="fa fa-clipboard" /> Copy Invite
                     <i className="fa fa-clipboard" /> Copy Invite
                   </button>
                   </button>
                   &nbsp;
                   &nbsp;

+ 51 - 0
public/app/features/users/UsersActionBar.test.tsx

@@ -0,0 +1,51 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import { UsersActionBar, Props } from './UsersActionBar';
+
+const setup = (propOverrides?: object) => {
+  const props: Props = {
+    searchQuery: '',
+    setUsersSearchQuery: jest.fn(),
+    showInvites: false,
+    pendingInvitesCount: 0,
+    canInvite: false,
+    externalUserMngLinkUrl: '',
+    externalUserMngLinkName: '',
+  };
+
+  Object.assign(props, propOverrides);
+
+  return shallow(<UsersActionBar {...props} />);
+};
+
+describe('Render', () => {
+  it('should render component', () => {
+    const wrapper = setup();
+
+    expect(wrapper).toMatchSnapshot();
+  });
+
+  it('should render pending invites button', () => {
+    const wrapper = setup({
+      pendingInvitesCount: 5,
+    });
+
+    expect(wrapper).toMatchSnapshot();
+  });
+
+  it('should show invite button', () => {
+    const wrapper = setup({
+      canInvite: true,
+    });
+
+    expect(wrapper).toMatchSnapshot();
+  });
+
+  it('should show external user management button', () => {
+    const wrapper = setup({
+      externalUserMngLinkUrl: 'some/url',
+    });
+
+    expect(wrapper).toMatchSnapshot();
+  });
+});

+ 5 - 1
public/app/features/users/UsersListPage.test.tsx

@@ -1,7 +1,7 @@
 import React from 'react';
 import React from 'react';
 import { shallow } from 'enzyme';
 import { shallow } from 'enzyme';
 import { UsersListPage, Props } from './UsersListPage';
 import { UsersListPage, Props } from './UsersListPage';
-import { NavModel, User } from 'app/types';
+import { Invitee, NavModel, User } from 'app/types';
 import { getMockUser } from './__mocks__/userMocks';
 import { getMockUser } from './__mocks__/userMocks';
 import appEvents from '../../core/app_events';
 import appEvents from '../../core/app_events';
 
 
@@ -13,7 +13,11 @@ const setup = (propOverrides?: object) => {
   const props: Props = {
   const props: Props = {
     navModel: {} as NavModel,
     navModel: {} as NavModel,
     users: [] as User[],
     users: [] as User[],
+    invitees: [] as Invitee[],
     searchQuery: '',
     searchQuery: '',
+    externalUserMngInfo: '',
+    revokeInvite: jest.fn(),
+    loadInvitees: jest.fn(),
     loadUsers: jest.fn(),
     loadUsers: jest.fn(),
     updateUser: jest.fn(),
     updateUser: jest.fn(),
     removeUser: jest.fn(),
     removeUser: jest.fn(),

+ 25 - 0
public/app/features/users/__mocks__/userMocks.ts

@@ -29,3 +29,28 @@ export const getMockUser = () => {
     userId: 2,
     userId: 2,
   };
   };
 };
 };
+
+export const getMockInvitees = (amount: number) => {
+  const invitees = [];
+
+  for (let i = 0; i <= amount; i++) {
+    invitees.push({
+      code: `asdfasdfsadf-${i}`,
+      createdOn: '2018-10-02',
+      email: `invitee-${i}@test.com`,
+      emailSent: true,
+      emailSentOn: '2018-10-02',
+      id: i,
+      invitedByEmail: 'admin@grafana.com',
+      invitedByLogin: 'admin',
+      invitedByName: 'admin',
+      name: `invitee-${i}`,
+      orgId: 1,
+      role: 'viewer',
+      status: 'not accepted',
+      url: `localhost/invite/$${i}`,
+    });
+  }
+
+  return invitees;
+};

+ 318 - 0
public/app/features/users/__snapshots__/InviteesTable.test.tsx.snap

@@ -0,0 +1,318 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Render should render component 1`] = `
+<table
+  className="filter-table form-inline"
+>
+  <thead>
+    <tr>
+      <th>
+        Email
+      </th>
+      <th>
+        Name
+      </th>
+      <th />
+      <th
+        style={
+          Object {
+            "width": "34px",
+          }
+        }
+      />
+    </tr>
+  </thead>
+  <tbody />
+</table>
+`;
+
+exports[`Render should render invitees 1`] = `
+<table
+  className="filter-table form-inline"
+>
+  <thead>
+    <tr>
+      <th>
+        Email
+      </th>
+      <th>
+        Name
+      </th>
+      <th />
+      <th
+        style={
+          Object {
+            "width": "34px",
+          }
+        }
+      />
+    </tr>
+  </thead>
+  <tbody>
+    <tr
+      key="0-0"
+    >
+      <td>
+        invitee-0@test.com
+      </td>
+      <td>
+        invitee-0
+      </td>
+      <td
+        className="text-right"
+      >
+        <button
+          className="btn btn-inverse btn-mini"
+          onClick={[Function]}
+        >
+          <textarea
+            readOnly={true}
+            style={
+              Object {
+                "position": "absolute",
+                "right": -1000,
+              }
+            }
+            value="localhost/invite/$0"
+          />
+          <i
+            className="fa fa-clipboard"
+          />
+           Copy Invite
+        </button>
+         
+      </td>
+      <td>
+        <button
+          className="btn btn-danger btn-mini"
+          onClick={[Function]}
+        >
+          <i
+            className="fa fa-remove"
+          />
+        </button>
+      </td>
+    </tr>
+    <tr
+      key="1-1"
+    >
+      <td>
+        invitee-1@test.com
+      </td>
+      <td>
+        invitee-1
+      </td>
+      <td
+        className="text-right"
+      >
+        <button
+          className="btn btn-inverse btn-mini"
+          onClick={[Function]}
+        >
+          <textarea
+            readOnly={true}
+            style={
+              Object {
+                "position": "absolute",
+                "right": -1000,
+              }
+            }
+            value="localhost/invite/$1"
+          />
+          <i
+            className="fa fa-clipboard"
+          />
+           Copy Invite
+        </button>
+         
+      </td>
+      <td>
+        <button
+          className="btn btn-danger btn-mini"
+          onClick={[Function]}
+        >
+          <i
+            className="fa fa-remove"
+          />
+        </button>
+      </td>
+    </tr>
+    <tr
+      key="2-2"
+    >
+      <td>
+        invitee-2@test.com
+      </td>
+      <td>
+        invitee-2
+      </td>
+      <td
+        className="text-right"
+      >
+        <button
+          className="btn btn-inverse btn-mini"
+          onClick={[Function]}
+        >
+          <textarea
+            readOnly={true}
+            style={
+              Object {
+                "position": "absolute",
+                "right": -1000,
+              }
+            }
+            value="localhost/invite/$2"
+          />
+          <i
+            className="fa fa-clipboard"
+          />
+           Copy Invite
+        </button>
+         
+      </td>
+      <td>
+        <button
+          className="btn btn-danger btn-mini"
+          onClick={[Function]}
+        >
+          <i
+            className="fa fa-remove"
+          />
+        </button>
+      </td>
+    </tr>
+    <tr
+      key="3-3"
+    >
+      <td>
+        invitee-3@test.com
+      </td>
+      <td>
+        invitee-3
+      </td>
+      <td
+        className="text-right"
+      >
+        <button
+          className="btn btn-inverse btn-mini"
+          onClick={[Function]}
+        >
+          <textarea
+            readOnly={true}
+            style={
+              Object {
+                "position": "absolute",
+                "right": -1000,
+              }
+            }
+            value="localhost/invite/$3"
+          />
+          <i
+            className="fa fa-clipboard"
+          />
+           Copy Invite
+        </button>
+         
+      </td>
+      <td>
+        <button
+          className="btn btn-danger btn-mini"
+          onClick={[Function]}
+        >
+          <i
+            className="fa fa-remove"
+          />
+        </button>
+      </td>
+    </tr>
+    <tr
+      key="4-4"
+    >
+      <td>
+        invitee-4@test.com
+      </td>
+      <td>
+        invitee-4
+      </td>
+      <td
+        className="text-right"
+      >
+        <button
+          className="btn btn-inverse btn-mini"
+          onClick={[Function]}
+        >
+          <textarea
+            readOnly={true}
+            style={
+              Object {
+                "position": "absolute",
+                "right": -1000,
+              }
+            }
+            value="localhost/invite/$4"
+          />
+          <i
+            className="fa fa-clipboard"
+          />
+           Copy Invite
+        </button>
+         
+      </td>
+      <td>
+        <button
+          className="btn btn-danger btn-mini"
+          onClick={[Function]}
+        >
+          <i
+            className="fa fa-remove"
+          />
+        </button>
+      </td>
+    </tr>
+    <tr
+      key="5-5"
+    >
+      <td>
+        invitee-5@test.com
+      </td>
+      <td>
+        invitee-5
+      </td>
+      <td
+        className="text-right"
+      >
+        <button
+          className="btn btn-inverse btn-mini"
+          onClick={[Function]}
+        >
+          <textarea
+            readOnly={true}
+            style={
+              Object {
+                "position": "absolute",
+                "right": -1000,
+              }
+            }
+            value="localhost/invite/$5"
+          />
+          <i
+            className="fa fa-clipboard"
+          />
+           Copy Invite
+        </button>
+         
+      </td>
+      <td>
+        <button
+          className="btn btn-danger btn-mini"
+          onClick={[Function]}
+        >
+          <i
+            className="fa fa-remove"
+          />
+        </button>
+      </td>
+    </tr>
+  </tbody>
+</table>
+`;

+ 141 - 0
public/app/features/users/__snapshots__/UsersActionBar.test.tsx.snap

@@ -0,0 +1,141 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Render should render component 1`] = `
+<div
+  className="page-action-bar"
+>
+  <div
+    className="gf-form gf-form--grow"
+  >
+    <label
+      className="gf-form--has-input-icon"
+    >
+      <input
+        className="gf-form-input width-20"
+        onChange={[Function]}
+        placeholder="Filter by name or type"
+        type="text"
+        value=""
+      />
+      <i
+        className="gf-form-input-icon fa fa-search"
+      />
+    </label>
+    <div
+      className="page-action-bar__spacer"
+    />
+  </div>
+</div>
+`;
+
+exports[`Render should render pending invites button 1`] = `
+<div
+  className="page-action-bar"
+>
+  <div
+    className="gf-form gf-form--grow"
+  >
+    <label
+      className="gf-form--has-input-icon"
+    >
+      <input
+        className="gf-form-input width-20"
+        onChange={[Function]}
+        placeholder="Filter by name or type"
+        type="text"
+        value=""
+      />
+      <i
+        className="gf-form-input-icon fa fa-search"
+      />
+    </label>
+    <div
+      className="page-action-bar__spacer"
+    />
+    <button
+      className="btn btn-inverse"
+      onClick={false}
+    >
+      Pending Invites (
+      5
+      )
+    </button>
+  </div>
+</div>
+`;
+
+exports[`Render should show external user management button 1`] = `
+<div
+  className="page-action-bar"
+>
+  <div
+    className="gf-form gf-form--grow"
+  >
+    <label
+      className="gf-form--has-input-icon"
+    >
+      <input
+        className="gf-form-input width-20"
+        onChange={[Function]}
+        placeholder="Filter by name or type"
+        type="text"
+        value=""
+      />
+      <i
+        className="gf-form-input-icon fa fa-search"
+      />
+    </label>
+    <div
+      className="page-action-bar__spacer"
+    />
+    <a
+      className="btn btn-success"
+      href="some/url"
+      target="_blank"
+    >
+      <i
+        className="fa fa-external-link-square"
+      />
+    </a>
+  </div>
+</div>
+`;
+
+exports[`Render should show invite button 1`] = `
+<div
+  className="page-action-bar"
+>
+  <div
+    className="gf-form gf-form--grow"
+  >
+    <label
+      className="gf-form--has-input-icon"
+    >
+      <input
+        className="gf-form-input width-20"
+        onChange={[Function]}
+        placeholder="Filter by name or type"
+        type="text"
+        value=""
+      />
+      <i
+        className="gf-form-input-icon fa fa-search"
+      />
+    </label>
+    <div
+      className="page-action-bar__spacer"
+    />
+    <a
+      className="btn btn-success"
+      href="org/users/invite"
+    >
+      <i
+        className="fa fa-plus"
+      />
+      <span>
+        Invite
+      </span>
+    </a>
+  </div>
+</div>
+`;

+ 2 - 10
public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap

@@ -8,16 +8,8 @@ exports[`Render should render component 1`] = `
   <div
   <div
     className="page-container page-body"
     className="page-container page-body"
   >
   >
-    <OrgActionBar
-      linkButton={
-        Object {
-          "href": "/org/users/add",
-          "title": "Add user",
-        }
-      }
-      searchQuery=""
-      setSearchQuery={[MockFunction]}
-      showLayoutMode={false}
+    <Connect(UsersActionBar)
+      showInvites={[Function]}
     />
     />
     <UsersTable
     <UsersTable
       onRemoveUser={[Function]}
       onRemoveUser={[Function]}

+ 405 - 409
public/app/features/users/__snapshots__/UsersTable.test.tsx.snap

@@ -1,448 +1,444 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 
 exports[`Render should render component 1`] = `
 exports[`Render should render component 1`] = `
-<div>
-  <table
-    className="filter-table form-inline"
-  >
-    <thead>
-      <tr>
-        <th />
-        <th>
-          Login
-        </th>
-        <th>
-          Email
-        </th>
-        <th>
-          Seen
-        </th>
-        <th>
-          Role
-        </th>
-        <th
-          style={
-            Object {
-              "width": "34px",
-            }
+<table
+  className="filter-table form-inline"
+>
+  <thead>
+    <tr>
+      <th />
+      <th>
+        Login
+      </th>
+      <th>
+        Email
+      </th>
+      <th>
+        Seen
+      </th>
+      <th>
+        Role
+      </th>
+      <th
+        style={
+          Object {
+            "width": "34px",
           }
           }
-        />
-      </tr>
-    </thead>
-    <tbody />
-  </table>
-</div>
+        }
+      />
+    </tr>
+  </thead>
+  <tbody />
+</table>
 `;
 `;
 
 
 exports[`Render should render users table 1`] = `
 exports[`Render should render users table 1`] = `
-<div>
-  <table
-    className="filter-table form-inline"
-  >
-    <thead>
-      <tr>
-        <th />
-        <th>
-          Login
-        </th>
-        <th>
-          Email
-        </th>
-        <th>
-          Seen
-        </th>
-        <th>
-          Role
-        </th>
-        <th
-          style={
-            Object {
-              "width": "34px",
-            }
+<table
+  className="filter-table form-inline"
+>
+  <thead>
+    <tr>
+      <th />
+      <th>
+        Login
+      </th>
+      <th>
+        Email
+      </th>
+      <th>
+        Seen
+      </th>
+      <th>
+        Role
+      </th>
+      <th
+        style={
+          Object {
+            "width": "34px",
           }
           }
-        />
-      </tr>
-    </thead>
-    <tbody>
-      <tr
-        key="0-0"
+        }
+      />
+    </tr>
+  </thead>
+  <tbody>
+    <tr
+      key="0-0"
+    >
+      <td
+        className="width-4 text-center"
       >
       >
-        <td
-          className="width-4 text-center"
+        <img
+          className="filter-table__avatar"
+          src="url/to/avatar"
+        />
+      </td>
+      <td>
+        user-0
+      </td>
+      <td>
+        <span
+          className="ellipsis"
         >
         >
-          <img
-            className="filter-table__avatar"
-            src="url/to/avatar"
-          />
-        </td>
-        <td>
-          user-0
-        </td>
-        <td>
-          <span
-            className="ellipsis"
-          >
-            user-0@test.com
-          </span>
-        </td>
-        <td />
-        <td>
-          <div
-            className="gf-form-select-wrapper width-12"
+          user-0@test.com
+        </span>
+      </td>
+      <td />
+      <td>
+        <div
+          className="gf-form-select-wrapper width-12"
+        >
+          <select
+            className="gf-form-input"
+            onChange={[Function]}
+            value="Admin"
           >
           >
-            <select
-              className="gf-form-input"
-              onChange={[Function]}
+            <option
+              key="Viewer-0"
+              value="Viewer"
+            >
+              Viewer
+            </option>
+            <option
+              key="Editor-1"
+              value="Editor"
+            >
+              Editor
+            </option>
+            <option
+              key="Admin-2"
               value="Admin"
               value="Admin"
             >
             >
-              <option
-                key="Viewer-0"
-                value="Viewer"
-              >
-                Viewer
-              </option>
-              <option
-                key="Editor-1"
-                value="Editor"
-              >
-                Editor
-              </option>
-              <option
-                key="Admin-2"
-                value="Admin"
-              >
-                Admin
-              </option>
-            </select>
-          </div>
-        </td>
-        <td>
-          <div
-            className="btn btn-danger btn-mini"
-            onClick={[Function]}
-          >
-            <i
-              className="fa fa-remove"
-            />
-          </div>
-        </td>
-      </tr>
-      <tr
-        key="1-1"
-      >
-        <td
-          className="width-4 text-center"
+              Admin
+            </option>
+          </select>
+        </div>
+      </td>
+      <td>
+        <div
+          className="btn btn-danger btn-mini"
+          onClick={[Function]}
         >
         >
-          <img
-            className="filter-table__avatar"
-            src="url/to/avatar"
+          <i
+            className="fa fa-remove"
           />
           />
-        </td>
-        <td>
-          user-1
-        </td>
-        <td>
-          <span
-            className="ellipsis"
-          >
-            user-1@test.com
-          </span>
-        </td>
-        <td />
-        <td>
-          <div
-            className="gf-form-select-wrapper width-12"
+        </div>
+      </td>
+    </tr>
+    <tr
+      key="1-1"
+    >
+      <td
+        className="width-4 text-center"
+      >
+        <img
+          className="filter-table__avatar"
+          src="url/to/avatar"
+        />
+      </td>
+      <td>
+        user-1
+      </td>
+      <td>
+        <span
+          className="ellipsis"
+        >
+          user-1@test.com
+        </span>
+      </td>
+      <td />
+      <td>
+        <div
+          className="gf-form-select-wrapper width-12"
+        >
+          <select
+            className="gf-form-input"
+            onChange={[Function]}
+            value="Admin"
           >
           >
-            <select
-              className="gf-form-input"
-              onChange={[Function]}
+            <option
+              key="Viewer-0"
+              value="Viewer"
+            >
+              Viewer
+            </option>
+            <option
+              key="Editor-1"
+              value="Editor"
+            >
+              Editor
+            </option>
+            <option
+              key="Admin-2"
               value="Admin"
               value="Admin"
             >
             >
-              <option
-                key="Viewer-0"
-                value="Viewer"
-              >
-                Viewer
-              </option>
-              <option
-                key="Editor-1"
-                value="Editor"
-              >
-                Editor
-              </option>
-              <option
-                key="Admin-2"
-                value="Admin"
-              >
-                Admin
-              </option>
-            </select>
-          </div>
-        </td>
-        <td>
-          <div
-            className="btn btn-danger btn-mini"
-            onClick={[Function]}
-          >
-            <i
-              className="fa fa-remove"
-            />
-          </div>
-        </td>
-      </tr>
-      <tr
-        key="2-2"
-      >
-        <td
-          className="width-4 text-center"
+              Admin
+            </option>
+          </select>
+        </div>
+      </td>
+      <td>
+        <div
+          className="btn btn-danger btn-mini"
+          onClick={[Function]}
         >
         >
-          <img
-            className="filter-table__avatar"
-            src="url/to/avatar"
+          <i
+            className="fa fa-remove"
           />
           />
-        </td>
-        <td>
-          user-2
-        </td>
-        <td>
-          <span
-            className="ellipsis"
-          >
-            user-2@test.com
-          </span>
-        </td>
-        <td />
-        <td>
-          <div
-            className="gf-form-select-wrapper width-12"
+        </div>
+      </td>
+    </tr>
+    <tr
+      key="2-2"
+    >
+      <td
+        className="width-4 text-center"
+      >
+        <img
+          className="filter-table__avatar"
+          src="url/to/avatar"
+        />
+      </td>
+      <td>
+        user-2
+      </td>
+      <td>
+        <span
+          className="ellipsis"
+        >
+          user-2@test.com
+        </span>
+      </td>
+      <td />
+      <td>
+        <div
+          className="gf-form-select-wrapper width-12"
+        >
+          <select
+            className="gf-form-input"
+            onChange={[Function]}
+            value="Admin"
           >
           >
-            <select
-              className="gf-form-input"
-              onChange={[Function]}
+            <option
+              key="Viewer-0"
+              value="Viewer"
+            >
+              Viewer
+            </option>
+            <option
+              key="Editor-1"
+              value="Editor"
+            >
+              Editor
+            </option>
+            <option
+              key="Admin-2"
               value="Admin"
               value="Admin"
             >
             >
-              <option
-                key="Viewer-0"
-                value="Viewer"
-              >
-                Viewer
-              </option>
-              <option
-                key="Editor-1"
-                value="Editor"
-              >
-                Editor
-              </option>
-              <option
-                key="Admin-2"
-                value="Admin"
-              >
-                Admin
-              </option>
-            </select>
-          </div>
-        </td>
-        <td>
-          <div
-            className="btn btn-danger btn-mini"
-            onClick={[Function]}
-          >
-            <i
-              className="fa fa-remove"
-            />
-          </div>
-        </td>
-      </tr>
-      <tr
-        key="3-3"
-      >
-        <td
-          className="width-4 text-center"
+              Admin
+            </option>
+          </select>
+        </div>
+      </td>
+      <td>
+        <div
+          className="btn btn-danger btn-mini"
+          onClick={[Function]}
         >
         >
-          <img
-            className="filter-table__avatar"
-            src="url/to/avatar"
+          <i
+            className="fa fa-remove"
           />
           />
-        </td>
-        <td>
-          user-3
-        </td>
-        <td>
-          <span
-            className="ellipsis"
-          >
-            user-3@test.com
-          </span>
-        </td>
-        <td />
-        <td>
-          <div
-            className="gf-form-select-wrapper width-12"
+        </div>
+      </td>
+    </tr>
+    <tr
+      key="3-3"
+    >
+      <td
+        className="width-4 text-center"
+      >
+        <img
+          className="filter-table__avatar"
+          src="url/to/avatar"
+        />
+      </td>
+      <td>
+        user-3
+      </td>
+      <td>
+        <span
+          className="ellipsis"
+        >
+          user-3@test.com
+        </span>
+      </td>
+      <td />
+      <td>
+        <div
+          className="gf-form-select-wrapper width-12"
+        >
+          <select
+            className="gf-form-input"
+            onChange={[Function]}
+            value="Admin"
           >
           >
-            <select
-              className="gf-form-input"
-              onChange={[Function]}
+            <option
+              key="Viewer-0"
+              value="Viewer"
+            >
+              Viewer
+            </option>
+            <option
+              key="Editor-1"
+              value="Editor"
+            >
+              Editor
+            </option>
+            <option
+              key="Admin-2"
               value="Admin"
               value="Admin"
             >
             >
-              <option
-                key="Viewer-0"
-                value="Viewer"
-              >
-                Viewer
-              </option>
-              <option
-                key="Editor-1"
-                value="Editor"
-              >
-                Editor
-              </option>
-              <option
-                key="Admin-2"
-                value="Admin"
-              >
-                Admin
-              </option>
-            </select>
-          </div>
-        </td>
-        <td>
-          <div
-            className="btn btn-danger btn-mini"
-            onClick={[Function]}
-          >
-            <i
-              className="fa fa-remove"
-            />
-          </div>
-        </td>
-      </tr>
-      <tr
-        key="4-4"
-      >
-        <td
-          className="width-4 text-center"
+              Admin
+            </option>
+          </select>
+        </div>
+      </td>
+      <td>
+        <div
+          className="btn btn-danger btn-mini"
+          onClick={[Function]}
         >
         >
-          <img
-            className="filter-table__avatar"
-            src="url/to/avatar"
+          <i
+            className="fa fa-remove"
           />
           />
-        </td>
-        <td>
-          user-4
-        </td>
-        <td>
-          <span
-            className="ellipsis"
-          >
-            user-4@test.com
-          </span>
-        </td>
-        <td />
-        <td>
-          <div
-            className="gf-form-select-wrapper width-12"
+        </div>
+      </td>
+    </tr>
+    <tr
+      key="4-4"
+    >
+      <td
+        className="width-4 text-center"
+      >
+        <img
+          className="filter-table__avatar"
+          src="url/to/avatar"
+        />
+      </td>
+      <td>
+        user-4
+      </td>
+      <td>
+        <span
+          className="ellipsis"
+        >
+          user-4@test.com
+        </span>
+      </td>
+      <td />
+      <td>
+        <div
+          className="gf-form-select-wrapper width-12"
+        >
+          <select
+            className="gf-form-input"
+            onChange={[Function]}
+            value="Admin"
           >
           >
-            <select
-              className="gf-form-input"
-              onChange={[Function]}
+            <option
+              key="Viewer-0"
+              value="Viewer"
+            >
+              Viewer
+            </option>
+            <option
+              key="Editor-1"
+              value="Editor"
+            >
+              Editor
+            </option>
+            <option
+              key="Admin-2"
               value="Admin"
               value="Admin"
             >
             >
-              <option
-                key="Viewer-0"
-                value="Viewer"
-              >
-                Viewer
-              </option>
-              <option
-                key="Editor-1"
-                value="Editor"
-              >
-                Editor
-              </option>
-              <option
-                key="Admin-2"
-                value="Admin"
-              >
-                Admin
-              </option>
-            </select>
-          </div>
-        </td>
-        <td>
-          <div
-            className="btn btn-danger btn-mini"
-            onClick={[Function]}
-          >
-            <i
-              className="fa fa-remove"
-            />
-          </div>
-        </td>
-      </tr>
-      <tr
-        key="5-5"
-      >
-        <td
-          className="width-4 text-center"
+              Admin
+            </option>
+          </select>
+        </div>
+      </td>
+      <td>
+        <div
+          className="btn btn-danger btn-mini"
+          onClick={[Function]}
         >
         >
-          <img
-            className="filter-table__avatar"
-            src="url/to/avatar"
+          <i
+            className="fa fa-remove"
           />
           />
-        </td>
-        <td>
-          user-5
-        </td>
-        <td>
-          <span
-            className="ellipsis"
-          >
-            user-5@test.com
-          </span>
-        </td>
-        <td />
-        <td>
-          <div
-            className="gf-form-select-wrapper width-12"
+        </div>
+      </td>
+    </tr>
+    <tr
+      key="5-5"
+    >
+      <td
+        className="width-4 text-center"
+      >
+        <img
+          className="filter-table__avatar"
+          src="url/to/avatar"
+        />
+      </td>
+      <td>
+        user-5
+      </td>
+      <td>
+        <span
+          className="ellipsis"
+        >
+          user-5@test.com
+        </span>
+      </td>
+      <td />
+      <td>
+        <div
+          className="gf-form-select-wrapper width-12"
+        >
+          <select
+            className="gf-form-input"
+            onChange={[Function]}
+            value="Admin"
           >
           >
-            <select
-              className="gf-form-input"
-              onChange={[Function]}
+            <option
+              key="Viewer-0"
+              value="Viewer"
+            >
+              Viewer
+            </option>
+            <option
+              key="Editor-1"
+              value="Editor"
+            >
+              Editor
+            </option>
+            <option
+              key="Admin-2"
               value="Admin"
               value="Admin"
             >
             >
-              <option
-                key="Viewer-0"
-                value="Viewer"
-              >
-                Viewer
-              </option>
-              <option
-                key="Editor-1"
-                value="Editor"
-              >
-                Editor
-              </option>
-              <option
-                key="Admin-2"
-                value="Admin"
-              >
-                Admin
-              </option>
-            </select>
-          </div>
-        </td>
-        <td>
-          <div
-            className="btn btn-danger btn-mini"
-            onClick={[Function]}
-          >
-            <i
-              className="fa fa-remove"
-            />
-          </div>
-        </td>
-      </tr>
-    </tbody>
-  </table>
-</div>
+              Admin
+            </option>
+          </select>
+        </div>
+      </td>
+      <td>
+        <div
+          className="btn btn-danger btn-mini"
+          onClick={[Function]}
+        >
+          <i
+            className="fa fa-remove"
+          />
+        </div>
+      </td>
+    </tr>
+  </tbody>
+</table>
 `;
 `;