mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
UserTableView: Show user name in table view (#18108)
* refactor to multiple rows * added name for org user struct * added name getorgusers * added user name to tableview * made test pass * updated userMocks to user name field * added missing UsersTable snapshot * added name on teammembers page, be able to search query for name, login and email * added the updated snapshots * conform to same sorting as output form * conform to previous way of using it * sort first by login and after by email, as it was before
This commit is contained in:
parent
e33cf32b97
commit
f05607d4c0
@ -111,6 +111,7 @@ type OrgUserDTO struct {
|
|||||||
OrgId int64 `json:"orgId"`
|
OrgId int64 `json:"orgId"`
|
||||||
UserId int64 `json:"userId"`
|
UserId int64 `json:"userId"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
|
Name string `json:"name"`
|
||||||
AvatarUrl string `json:"avatarUrl"`
|
AvatarUrl string `json:"avatarUrl"`
|
||||||
Login string `json:"login"`
|
Login string `json:"login"`
|
||||||
Role string `json:"role"`
|
Role string `json:"role"`
|
||||||
|
@ -70,6 +70,7 @@ type TeamMemberDTO struct {
|
|||||||
External bool `json:"-"`
|
External bool `json:"-"`
|
||||||
AuthModule string `json:"auth_module"`
|
AuthModule string `json:"auth_module"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
|
Name string `json:"name"`
|
||||||
Login string `json:"login"`
|
Login string `json:"login"`
|
||||||
AvatarUrl string `json:"avatarUrl"`
|
AvatarUrl string `json:"avatarUrl"`
|
||||||
Labels []string `json:"labels"`
|
Labels []string `json:"labels"`
|
||||||
|
@ -120,7 +120,15 @@ func GetOrgUsers(query *m.GetOrgUsersQuery) error {
|
|||||||
sess.Limit(query.Limit, 0)
|
sess.Limit(query.Limit, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
sess.Cols("org_user.org_id", "org_user.user_id", "user.email", "user.login", "org_user.role", "user.last_seen_at")
|
sess.Cols(
|
||||||
|
"org_user.org_id",
|
||||||
|
"org_user.user_id",
|
||||||
|
"user.email",
|
||||||
|
"user.name",
|
||||||
|
"user.login",
|
||||||
|
"org_user.role",
|
||||||
|
"user.last_seen_at",
|
||||||
|
)
|
||||||
sess.Asc("user.email", "user.login")
|
sess.Asc("user.email", "user.login")
|
||||||
|
|
||||||
if err := sess.Find(&query.Result); err != nil {
|
if err := sess.Find(&query.Result); err != nil {
|
||||||
|
@ -387,7 +387,17 @@ func GetTeamMembers(query *models.GetTeamMembersQuery) error {
|
|||||||
if query.External {
|
if query.External {
|
||||||
sess.Where("team_member.external=?", dialect.BooleanStr(true))
|
sess.Where("team_member.external=?", dialect.BooleanStr(true))
|
||||||
}
|
}
|
||||||
sess.Cols("team_member.org_id", "team_member.team_id", "team_member.user_id", "user.email", "user.login", "team_member.external", "team_member.permission", "user_auth.auth_module")
|
sess.Cols(
|
||||||
|
"team_member.org_id",
|
||||||
|
"team_member.team_id",
|
||||||
|
"team_member.user_id",
|
||||||
|
"user.email",
|
||||||
|
"user.name",
|
||||||
|
"user.login",
|
||||||
|
"team_member.external",
|
||||||
|
"team_member.permission",
|
||||||
|
"user_auth.auth_module",
|
||||||
|
)
|
||||||
sess.Asc("user.login", "user.email")
|
sess.Asc("user.login", "user.email")
|
||||||
|
|
||||||
err := sess.Find(&query.Result)
|
err := sess.Find(&query.Result)
|
||||||
|
@ -74,8 +74,9 @@ describe('Functions', () => {
|
|||||||
teamId: 2,
|
teamId: 2,
|
||||||
avatarUrl: '',
|
avatarUrl: '',
|
||||||
email: 'user@user.org',
|
email: 'user@user.org',
|
||||||
labels: [],
|
|
||||||
login: 'member',
|
login: 'member',
|
||||||
|
name: 'member',
|
||||||
|
labels: [],
|
||||||
permission: TeamPermissionLevel.Member,
|
permission: TeamPermissionLevel.Member,
|
||||||
};
|
};
|
||||||
const { instance } = setup({ member });
|
const { instance } = setup({ member });
|
||||||
|
@ -82,6 +82,7 @@ export class TeamMemberRow extends PureComponent<Props> {
|
|||||||
</td>
|
</td>
|
||||||
<td>{member.login}</td>
|
<td>{member.login}</td>
|
||||||
<td>{member.email}</td>
|
<td>{member.email}</td>
|
||||||
|
<td>{member.name}</td>
|
||||||
{this.renderPermissions(member)}
|
{this.renderPermissions(member)}
|
||||||
{syncEnabled && this.renderLabels(member.labels)}
|
{syncEnabled && this.renderLabels(member.labels)}
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
|
@ -115,8 +115,9 @@ export class TeamMembers extends PureComponent<Props, State> {
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th />
|
<th />
|
||||||
<th>Name</th>
|
<th>Login</th>
|
||||||
<th>Email</th>
|
<th>Email</th>
|
||||||
|
<th>Name</th>
|
||||||
<WithFeatureToggle featureToggle={editorsCanAdmin}>
|
<WithFeatureToggle featureToggle={editorsCanAdmin}>
|
||||||
<th>Permission</th>
|
<th>Permission</th>
|
||||||
</WithFeatureToggle>
|
</WithFeatureToggle>
|
||||||
|
@ -36,6 +36,7 @@ export const getMockTeamMembers = (amount: number, teamAdminId: number): TeamMem
|
|||||||
teamId: 1,
|
teamId: 1,
|
||||||
avatarUrl: 'some/url/',
|
avatarUrl: 'some/url/',
|
||||||
email: 'test@test.com',
|
email: 'test@test.com',
|
||||||
|
name: 'testName',
|
||||||
login: `testUser-${i}`,
|
login: `testUser-${i}`,
|
||||||
labels: ['label 1', 'label 2'],
|
labels: ['label 1', 'label 2'],
|
||||||
permission: i === teamAdminId ? TeamPermissionLevel.Admin : TeamPermissionLevel.Member,
|
permission: i === teamAdminId ? TeamPermissionLevel.Admin : TeamPermissionLevel.Member,
|
||||||
@ -51,6 +52,7 @@ export const getMockTeamMember = (): TeamMember => {
|
|||||||
teamId: 1,
|
teamId: 1,
|
||||||
avatarUrl: 'some/url/',
|
avatarUrl: 'some/url/',
|
||||||
email: 'test@test.com',
|
email: 'test@test.com',
|
||||||
|
name: 'testName',
|
||||||
login: 'testUser',
|
login: 'testUser',
|
||||||
labels: [],
|
labels: [],
|
||||||
permission: TeamPermissionLevel.Member,
|
permission: TeamPermissionLevel.Member,
|
||||||
|
@ -18,6 +18,9 @@ exports[`Render should render team members when sync enabled 1`] = `
|
|||||||
<td>
|
<td>
|
||||||
test@test.com
|
test@test.com
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
testName
|
||||||
|
</td>
|
||||||
<Component
|
<Component
|
||||||
featureToggle={false}
|
featureToggle={false}
|
||||||
>
|
>
|
||||||
@ -71,6 +74,9 @@ exports[`Render when feature toggle editorsCanAdmin is turned off should not ren
|
|||||||
<td>
|
<td>
|
||||||
test@test.com
|
test@test.com
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
testName
|
||||||
|
</td>
|
||||||
<Component
|
<Component
|
||||||
featureToggle={false}
|
featureToggle={false}
|
||||||
>
|
>
|
||||||
@ -157,6 +163,9 @@ exports[`Render when feature toggle editorsCanAdmin is turned on should render p
|
|||||||
<td>
|
<td>
|
||||||
test@test.com
|
test@test.com
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
testName
|
||||||
|
</td>
|
||||||
<Component
|
<Component
|
||||||
featureToggle={true}
|
featureToggle={true}
|
||||||
>
|
>
|
||||||
@ -243,6 +252,9 @@ exports[`Render when feature toggle editorsCanAdmin is turned on should render s
|
|||||||
<td>
|
<td>
|
||||||
test@test.com
|
test@test.com
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
testName
|
||||||
|
</td>
|
||||||
<Component
|
<Component
|
||||||
featureToggle={true}
|
featureToggle={true}
|
||||||
>
|
>
|
||||||
|
@ -64,11 +64,14 @@ exports[`Render should render component 1`] = `
|
|||||||
<tr>
|
<tr>
|
||||||
<th />
|
<th />
|
||||||
<th>
|
<th>
|
||||||
Name
|
Login
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
Email
|
Email
|
||||||
</th>
|
</th>
|
||||||
|
<th>
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
<Component
|
<Component
|
||||||
featureToggle={false}
|
featureToggle={false}
|
||||||
>
|
>
|
||||||
@ -155,11 +158,14 @@ exports[`Render should render team members 1`] = `
|
|||||||
<tr>
|
<tr>
|
||||||
<th />
|
<th />
|
||||||
<th>
|
<th>
|
||||||
Name
|
Login
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
Email
|
Email
|
||||||
</th>
|
</th>
|
||||||
|
<th>
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
<Component
|
<Component
|
||||||
featureToggle={false}
|
featureToggle={false}
|
||||||
>
|
>
|
||||||
@ -189,6 +195,7 @@ exports[`Render should render team members 1`] = `
|
|||||||
"label 2",
|
"label 2",
|
||||||
],
|
],
|
||||||
"login": "testUser-1",
|
"login": "testUser-1",
|
||||||
|
"name": "testName",
|
||||||
"permission": 0,
|
"permission": 0,
|
||||||
"teamId": 1,
|
"teamId": 1,
|
||||||
"userId": 1,
|
"userId": 1,
|
||||||
@ -209,6 +216,7 @@ exports[`Render should render team members 1`] = `
|
|||||||
"label 2",
|
"label 2",
|
||||||
],
|
],
|
||||||
"login": "testUser-2",
|
"login": "testUser-2",
|
||||||
|
"name": "testName",
|
||||||
"permission": 0,
|
"permission": 0,
|
||||||
"teamId": 1,
|
"teamId": 1,
|
||||||
"userId": 2,
|
"userId": 2,
|
||||||
@ -229,6 +237,7 @@ exports[`Render should render team members 1`] = `
|
|||||||
"label 2",
|
"label 2",
|
||||||
],
|
],
|
||||||
"login": "testUser-3",
|
"login": "testUser-3",
|
||||||
|
"name": "testName",
|
||||||
"permission": 0,
|
"permission": 0,
|
||||||
"teamId": 1,
|
"teamId": 1,
|
||||||
"userId": 3,
|
"userId": 3,
|
||||||
@ -249,6 +258,7 @@ exports[`Render should render team members 1`] = `
|
|||||||
"label 2",
|
"label 2",
|
||||||
],
|
],
|
||||||
"login": "testUser-4",
|
"login": "testUser-4",
|
||||||
|
"name": "testName",
|
||||||
"permission": 0,
|
"permission": 0,
|
||||||
"teamId": 1,
|
"teamId": 1,
|
||||||
"userId": 4,
|
"userId": 4,
|
||||||
@ -269,6 +279,7 @@ exports[`Render should render team members 1`] = `
|
|||||||
"label 2",
|
"label 2",
|
||||||
],
|
],
|
||||||
"login": "testUser-5",
|
"login": "testUser-5",
|
||||||
|
"name": "testName",
|
||||||
"permission": 4,
|
"permission": 4,
|
||||||
"teamId": 1,
|
"teamId": 1,
|
||||||
"userId": 5,
|
"userId": 5,
|
||||||
|
@ -26,7 +26,7 @@ export const getTeamMembers = (state: TeamState) => {
|
|||||||
const regex = RegExp(state.searchMemberQuery, 'i');
|
const regex = RegExp(state.searchMemberQuery, 'i');
|
||||||
|
|
||||||
return state.members.filter(member => {
|
return state.members.filter(member => {
|
||||||
return regex.test(member.login) || regex.test(member.email);
|
return regex.test(member.login) || regex.test(member.email) || regex.test(member.name);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ export class UsersActionBar extends PureComponent<Props> {
|
|||||||
inputClassName="gf-form-input width-20"
|
inputClassName="gf-form-input width-20"
|
||||||
value={searchQuery}
|
value={searchQuery}
|
||||||
onChange={setUsersSearchQuery}
|
onChange={setUsersSearchQuery}
|
||||||
placeholder="Filter by name or type"
|
placeholder="Filter by email, login or name"
|
||||||
/>
|
/>
|
||||||
{pendingInvitesCount > 0 && (
|
{pendingInvitesCount > 0 && (
|
||||||
<div style={{ marginLeft: '1rem' }}>
|
<div style={{ marginLeft: '1rem' }}>
|
||||||
|
@ -17,6 +17,7 @@ const UsersTable: FC<Props> = props => {
|
|||||||
<th />
|
<th />
|
||||||
<th>Login</th>
|
<th>Login</th>
|
||||||
<th>Email</th>
|
<th>Email</th>
|
||||||
|
<th>Name</th>
|
||||||
<th>Seen</th>
|
<th>Seen</th>
|
||||||
<th>Role</th>
|
<th>Role</th>
|
||||||
<th style={{ width: '34px' }} />
|
<th style={{ width: '34px' }} />
|
||||||
@ -33,6 +34,7 @@ const UsersTable: FC<Props> = props => {
|
|||||||
<td>
|
<td>
|
||||||
<span className="ellipsis">{user.email}</span>
|
<span className="ellipsis">{user.email}</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td>{user.name}</td>
|
||||||
<td>{user.lastSeenAtAge}</td>
|
<td>{user.lastSeenAtAge}</td>
|
||||||
<td>
|
<td>
|
||||||
<div className="gf-form-select-wrapper width-12">
|
<div className="gf-form-select-wrapper width-12">
|
||||||
|
@ -5,6 +5,7 @@ export const getMockUsers = (amount: number) => {
|
|||||||
users.push({
|
users.push({
|
||||||
avatarUrl: 'url/to/avatar',
|
avatarUrl: 'url/to/avatar',
|
||||||
email: `user-${i}@test.com`,
|
email: `user-${i}@test.com`,
|
||||||
|
name: `user-${i} test`,
|
||||||
lastSeenAt: '2018-10-01',
|
lastSeenAt: '2018-10-01',
|
||||||
lastSeenAtAge: '',
|
lastSeenAtAge: '',
|
||||||
login: `user-${i}`,
|
login: `user-${i}`,
|
||||||
@ -21,6 +22,7 @@ export const getMockUser = () => {
|
|||||||
return {
|
return {
|
||||||
avatarUrl: 'url/to/avatar',
|
avatarUrl: 'url/to/avatar',
|
||||||
email: `user@test.com`,
|
email: `user@test.com`,
|
||||||
|
name: 'user test',
|
||||||
lastSeenAt: '2018-10-01',
|
lastSeenAt: '2018-10-01',
|
||||||
lastSeenAtAge: '',
|
lastSeenAtAge: '',
|
||||||
login: `user`,
|
login: `user`,
|
||||||
|
@ -11,7 +11,7 @@ exports[`Render should render component 1`] = `
|
|||||||
inputClassName="gf-form-input width-20"
|
inputClassName="gf-form-input width-20"
|
||||||
labelClassName="gf-form--has-input-icon"
|
labelClassName="gf-form--has-input-icon"
|
||||||
onChange={[MockFunction]}
|
onChange={[MockFunction]}
|
||||||
placeholder="Filter by name or type"
|
placeholder="Filter by email, login or name"
|
||||||
value=""
|
value=""
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
@ -32,7 +32,7 @@ exports[`Render should render pending invites button 1`] = `
|
|||||||
inputClassName="gf-form-input width-20"
|
inputClassName="gf-form-input width-20"
|
||||||
labelClassName="gf-form--has-input-icon"
|
labelClassName="gf-form--has-input-icon"
|
||||||
onChange={[MockFunction]}
|
onChange={[MockFunction]}
|
||||||
placeholder="Filter by name or type"
|
placeholder="Filter by email, login or name"
|
||||||
value=""
|
value=""
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
@ -77,7 +77,7 @@ exports[`Render should show external user management button 1`] = `
|
|||||||
inputClassName="gf-form-input width-20"
|
inputClassName="gf-form-input width-20"
|
||||||
labelClassName="gf-form--has-input-icon"
|
labelClassName="gf-form--has-input-icon"
|
||||||
onChange={[MockFunction]}
|
onChange={[MockFunction]}
|
||||||
placeholder="Filter by name or type"
|
placeholder="Filter by email, login or name"
|
||||||
value=""
|
value=""
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
@ -104,7 +104,7 @@ exports[`Render should show invite button 1`] = `
|
|||||||
inputClassName="gf-form-input width-20"
|
inputClassName="gf-form-input width-20"
|
||||||
labelClassName="gf-form--has-input-icon"
|
labelClassName="gf-form--has-input-icon"
|
||||||
onChange={[MockFunction]}
|
onChange={[MockFunction]}
|
||||||
placeholder="Filter by name or type"
|
placeholder="Filter by email, login or name"
|
||||||
value=""
|
value=""
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
@ -13,6 +13,9 @@ exports[`Render should render component 1`] = `
|
|||||||
<th>
|
<th>
|
||||||
Email
|
Email
|
||||||
</th>
|
</th>
|
||||||
|
<th>
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
<th>
|
<th>
|
||||||
Seen
|
Seen
|
||||||
</th>
|
</th>
|
||||||
@ -45,6 +48,9 @@ exports[`Render should render users table 1`] = `
|
|||||||
<th>
|
<th>
|
||||||
Email
|
Email
|
||||||
</th>
|
</th>
|
||||||
|
<th>
|
||||||
|
Name
|
||||||
|
</th>
|
||||||
<th>
|
<th>
|
||||||
Seen
|
Seen
|
||||||
</th>
|
</th>
|
||||||
@ -82,6 +88,9 @@ exports[`Render should render users table 1`] = `
|
|||||||
user-0@test.com
|
user-0@test.com
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
user-0 test
|
||||||
|
</td>
|
||||||
<td />
|
<td />
|
||||||
<td>
|
<td>
|
||||||
<div
|
<div
|
||||||
@ -145,6 +154,9 @@ exports[`Render should render users table 1`] = `
|
|||||||
user-1@test.com
|
user-1@test.com
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
user-1 test
|
||||||
|
</td>
|
||||||
<td />
|
<td />
|
||||||
<td>
|
<td>
|
||||||
<div
|
<div
|
||||||
@ -208,6 +220,9 @@ exports[`Render should render users table 1`] = `
|
|||||||
user-2@test.com
|
user-2@test.com
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
user-2 test
|
||||||
|
</td>
|
||||||
<td />
|
<td />
|
||||||
<td>
|
<td>
|
||||||
<div
|
<div
|
||||||
@ -271,6 +286,9 @@ exports[`Render should render users table 1`] = `
|
|||||||
user-3@test.com
|
user-3@test.com
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
user-3 test
|
||||||
|
</td>
|
||||||
<td />
|
<td />
|
||||||
<td>
|
<td>
|
||||||
<div
|
<div
|
||||||
@ -334,6 +352,9 @@ exports[`Render should render users table 1`] = `
|
|||||||
user-4@test.com
|
user-4@test.com
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
user-4 test
|
||||||
|
</td>
|
||||||
<td />
|
<td />
|
||||||
<td>
|
<td>
|
||||||
<div
|
<div
|
||||||
@ -397,6 +418,9 @@ exports[`Render should render users table 1`] = `
|
|||||||
user-5@test.com
|
user-5@test.com
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
user-5 test
|
||||||
|
</td>
|
||||||
<td />
|
<td />
|
||||||
<td>
|
<td>
|
||||||
<div
|
<div
|
||||||
|
@ -4,7 +4,7 @@ export const getUsers = (state: UsersState) => {
|
|||||||
const regex = new RegExp(state.searchQuery, 'i');
|
const regex = new RegExp(state.searchQuery, 'i');
|
||||||
|
|
||||||
return state.users.filter(user => {
|
return state.users.filter(user => {
|
||||||
return regex.test(user.login) || regex.test(user.email);
|
return regex.test(user.login) || regex.test(user.email) || regex.test(user.name);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ export interface TeamMember {
|
|||||||
teamId: number;
|
teamId: number;
|
||||||
avatarUrl: string;
|
avatarUrl: string;
|
||||||
email: string;
|
email: string;
|
||||||
|
name: string;
|
||||||
login: string;
|
login: string;
|
||||||
labels: string[];
|
labels: string[];
|
||||||
permission: number;
|
permission: number;
|
||||||
|
@ -6,6 +6,7 @@ export interface OrgUser {
|
|||||||
lastSeenAt: string;
|
lastSeenAt: string;
|
||||||
lastSeenAtAge: string;
|
lastSeenAtAge: string;
|
||||||
login: string;
|
login: string;
|
||||||
|
name: string;
|
||||||
orgId: number;
|
orgId: number;
|
||||||
role: string;
|
role: string;
|
||||||
userId: number;
|
userId: number;
|
||||||
|
Loading…
Reference in New Issue
Block a user