Commit da68b858 by Marcus Efraimsson

display team member labels

parent 9a6446c2
...@@ -12,6 +12,7 @@ const setup = (propOverrides?: object) => { ...@@ -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', () => { ...@@ -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', () => {
......
...@@ -3,6 +3,7 @@ import { connect } from 'react-redux'; ...@@ -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 { ...@@ -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> { ...@@ -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> { ...@@ -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> { ...@@ -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> { ...@@ -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>
......
...@@ -63,7 +63,7 @@ export class TeamPages extends PureComponent<Props, State> { ...@@ -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 />;
......
...@@ -35,6 +35,7 @@ export const getMockTeamMembers = (amount: number): TeamMember[] => { ...@@ -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 => { ...@@ -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: [],
}; };
}; };
......
...@@ -315,3 +315,305 @@ exports[`Render should render team members 1`] = ` ...@@ -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>
`;
...@@ -29,7 +29,9 @@ exports[`Render should render member page if team not empty 1`] = ` ...@@ -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>
`; `;
......
...@@ -12,6 +12,7 @@ export interface TeamMember { ...@@ -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 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment