mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
display team member labels
This commit is contained in:
parent
9a6446c2b5
commit
da68b858d7
@ -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', () => {
|
||||||
|
@ -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>
|
||||||
|
@ -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[] => {
|
|||||||
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: [],
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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`] = `
|
|||||||
<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 {
|
|||||||
avatarUrl: string;
|
avatarUrl: string;
|
||||||
email: string;
|
email: string;
|
||||||
login: string;
|
login: string;
|
||||||
|
labels: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TeamGroup {
|
export interface TeamGroup {
|
||||||
|
Loading…
Reference in New Issue
Block a user