Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cases] Use the new internal users API in the UI #150432

Merged
merged 36 commits into from
Feb 11, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
0052783
Create endpoint
cnasikas Jan 25, 2023
dc76d81
Add integration tests
cnasikas Jan 27, 2023
da0b433
Fix types
cnasikas Jan 27, 2023
9e32bbf
Merge branch 'main' into user_actions_users_api
cnasikas Jan 30, 2023
c80ca5f
Fix SO test
cnasikas Jan 31, 2023
3cedccf
Change response structure
cnasikas Jan 31, 2023
1327690
Merge branch 'main' into user_actions_users_api
cnasikas Jan 31, 2023
1479e88
Fix imports
cnasikas Jan 31, 2023
1b2804e
Improvements
cnasikas Jan 31, 2023
74a1b5b
Tests for basic license
cnasikas Jan 31, 2023
5765a73
Merge branch 'main' into user_actions_users_api
cnasikas Jan 31, 2023
8d042ac
Merge branch 'main' into user_actions_users_api
cnasikas Feb 2, 2023
b69eb79
PR feedback
cnasikas Feb 2, 2023
68802de
Better structure
cnasikas Feb 3, 2023
8cf7876
PR feedback
cnasikas Feb 3, 2023
c02905d
Fix tests
cnasikas Feb 3, 2023
2163590
Merge branch 'main' into user_actions_users_api
cnasikas Feb 5, 2023
36d5548
Better naming
cnasikas Feb 5, 2023
39217c2
Create useGetCaseUsers hook
cnasikas Feb 5, 2023
4f1ffbb
Rename ElasticUser to CaseUser
cnasikas Feb 6, 2023
f1f1f1c
Merge branch 'main' into use_users_api_ui
cnasikas Feb 6, 2023
b3a9716
Merge branch 'main' into use_users_api_ui
cnasikas Feb 6, 2023
ca455b6
Change to the new API
cnasikas Feb 6, 2023
d943837
Fix tests & types
cnasikas Feb 7, 2023
d73d7fe
Merge branch 'main' into use_users_api_ui
cnasikas Feb 8, 2023
f8e07f9
Merge branch 'main' into use_users_api_ui
cnasikas Feb 9, 2023
e8193ff
Fix display name when rendering users
cnasikas Feb 9, 2023
377cd88
Add assignees as participants
cnasikas Feb 9, 2023
83331e4
Fallback reporter
cnasikas Feb 9, 2023
d8e94d8
Add unit tests
cnasikas Feb 9, 2023
a2ca4c6
Fix tests
cnasikas Feb 9, 2023
c9be240
Fix types
cnasikas Feb 9, 2023
1854fd8
PR feedback
cnasikas Feb 10, 2023
b7d8711
Sort user list
cnasikas Feb 10, 2023
e439622
Merge branch 'main' into use_users_api_ui
cnasikas Feb 11, 2023
3475370
Fix tests
cnasikas Feb 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ export const CaseViewActivity = ({
users={reporterAsArray}
userProfiles={userProfiles}
/>
{caseUsers?.participants ? (
{caseUsers != null ? (
<UserList
dataTestSubj="case-view-user-list-participants"
theCase={caseData}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
*/

import React from 'react';
import { shallow } from 'enzyme';
import { UserList } from './user_list';
import * as i18n from '../translations';
import { basicCase } from '../../../containers/mock';
import { useCaseViewNavigation } from '../../../common/navigation/hooks';
import type { AppMockRenderer } from '../../../common/mock';
import { createAppMockRenderer } from '../../../common/mock';
import userEvent from '@testing-library/user-event';

jest.mock('../../../common/navigation/hooks');

Expand All @@ -27,15 +29,17 @@ describe('UserList ', () => {

const open = jest.fn();
const getCaseViewUrl = jest.fn().mockReturnValue(caseLink);
let appMockRender: AppMockRenderer;

beforeEach(() => {
jest.clearAllMocks();
appMockRender = createAppMockRenderer();
useCaseViewNavigationMock.mockReturnValue({ getCaseViewUrl });
window.open = open;
});

it('triggers mailto when email icon clicked', () => {
const wrapper = shallow(
const result = appMockRender.render(
<UserList
theCase={basicCase}
headline={i18n.REPORTER}
Expand All @@ -47,11 +51,37 @@ describe('UserList ', () => {
/>
);

wrapper.find('[data-test-subj="user-list-email-button"]').simulate('click');
userEvent.click(result.getByTestId('user-list-email-button'));

expect(open).toBeCalledWith(
`mailto:${user.email}?subject=${i18n.EMAIL_SUBJECT(title)}&body=${i18n.EMAIL_BODY(caseLink)}`,
'_blank'
);
});

it('sort the users correctly', () => {
const result = appMockRender.render(
<UserList
theCase={basicCase}
headline={i18n.REPORTER}
users={[
{
user: { ...user, full_name: 'Cases' },
},
{
user: { ...user, username: 'elastic', email: '[email protected]', full_name: null },
},
{
user: { ...user, username: 'test', full_name: null, email: null },
},
]}
/>
);

const userProfiles = result.getAllByTestId('user-profile-username');

expect(userProfiles[0].textContent).toBe('Cases');
expect(userProfiles[1].textContent).toBe('[email protected]');
expect(userProfiles[2].textContent).toBe('test');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import React, { useCallback } from 'react';
import { isEmpty } from 'lodash/fp';
import { sortBy } from 'lodash';

import {
EuiButtonIcon,
Expand All @@ -26,6 +27,7 @@ import * as i18n from '../translations';
import type { CaseUserWithProfileInfo, UserInfoWithAvatar } from '../../user_profiles/types';
import { HoverableUserWithAvatar } from '../../user_profiles/hoverable_user_with_avatar';
import { convertToUserInfo } from '../../user_profiles/user_converter';
import { getSortField } from '../../user_profiles/sort';

interface UserListProps {
theCase: Case;
Expand Down Expand Up @@ -90,8 +92,9 @@ export const UserList: React.FC<UserListProps> = React.memo(
);

const validUsers = getValidUsers(users, userProfiles ?? new Map());
const orderedUsers = sortBy(validUsers, getSortField);

if (validUsers.length === 0) {
if (orderedUsers.length === 0) {
return null;
}

Expand All @@ -107,7 +110,7 @@ export const UserList: React.FC<UserListProps> = React.memo(
</EuiFlexItem>
</EuiFlexGroup>
)}
{renderUsers(validUsers, handleSendEmail)}
{renderUsers(orderedUsers, handleSendEmail)}
</EuiText>
</EuiFlexItem>
);
Expand Down
14 changes: 8 additions & 6 deletions x-pack/plugins/cases/public/components/user_profiles/sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import type { UserProfileWithAvatar } from '@kbn/user-profile-components';
import { sortBy } from 'lodash';
import { NO_ASSIGNEES_VALUE } from '../all_cases/assignees_filter';
import type { CurrentUserProfile } from '../types';
import type { AssigneesFilteringSelection } from './types';

export const getSortField = (profile: UserProfileWithAvatar) =>
profile.user.full_name?.toLowerCase() ??
profile.user.email?.toLowerCase() ??
profile.user.username.toLowerCase();
import { UNKNOWN } from './translations';
import type { AssigneesFilteringSelection, UserInfoWithAvatar } from './types';

export const getSortField = (profile: UserProfileWithAvatar | UserInfoWithAvatar) =>
profile.user?.full_name?.toLowerCase() ??
profile.user?.email?.toLowerCase() ??
profile.user?.username.toLowerCase() ??
UNKNOWN;

export const moveCurrentUserToBeginning = <T extends { uid: string }>(
currentUserProfile?: T,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { UserProfileBulkGetParams, UserProfileServiceStart } from '@kbn/security
import { INTERNAL_SUGGEST_USER_PROFILES_URL } from '@kbn/cases-plugin/common/constants';
import { SuggestUserProfilesRequest } from '@kbn/cases-plugin/common/api';
import { UserProfileService } from '@kbn/cases-plugin/server/services';
import { UserProfileAvatarData } from '@kbn/security-plugin/common';
import { superUser } from '../authentication/users';
import { User } from '../authentication/types';
import { getSpaceUrlPrefix } from './helpers';
Expand Down Expand Up @@ -70,6 +71,31 @@ export const suggestUserProfiles = async ({
return profiles;
};

/**
* Updates the avatar of a user.
* The API needs a valid user session.
* The session acts as the user identifier
* whose the avatar is updated.
*/
export const updateUserProfileAvatar = async ({
supertest,
req,
expectedHttpCode = 200,
headers = {},
}: {
supertest: SuperTest.SuperTest<SuperTest.Test>;
req: UserProfileAvatarData;
expectedHttpCode?: number;
headers?: Record<string, unknown>;
}): Promise<void> => {
await supertest
.post('/internal/security/user_profile/_data')
.set('kbn-xsrf', 'true')
.set(headers)
.send({ avatar: req })
.expect(expectedHttpCode);
};

export const loginUsers = async ({
supertest,
users = [superUser],
Expand Down
Loading