Commit ee03cd5c authored by David O'Regan's avatar David O'Regan Committed by Olena Horal-Koretska

Fix(oncallschedules): limit users to current project

Limit users available for rotation shift
selection to current project
and allow user avatars to render by
passing the correct property
parent 8940e122
query searchProjectMembers($fullPath: ID!, $search: String) {
project(fullPath: $fullPath) {
projectMembers(search: $search) {
nodes {
user {
id
name
username
avatarUrl
}
}
}
}
}
...@@ -8,7 +8,7 @@ import getOncallSchedulesWithRotationsQuery from 'ee/oncall_schedules/graphql/qu ...@@ -8,7 +8,7 @@ import getOncallSchedulesWithRotationsQuery from 'ee/oncall_schedules/graphql/qu
import { updateStoreAfterRotationEdit } from 'ee/oncall_schedules/utils/cache_updates'; import { updateStoreAfterRotationEdit } from 'ee/oncall_schedules/utils/cache_updates';
import { isNameFieldValid, getParticipantsForSave } from 'ee/oncall_schedules/utils/common_utils'; import { isNameFieldValid, getParticipantsForSave } from 'ee/oncall_schedules/utils/common_utils';
import createFlash, { FLASH_TYPES } from '~/flash'; import createFlash, { FLASH_TYPES } from '~/flash';
import usersSearchQuery from '~/graphql_shared/queries/users_search.query.graphql'; import searchProjectMembersQuery from '~/graphql_shared/queries/project_user_members_search.query.graphql';
import { format24HourTimeStringFromInt, formatDate } from '~/lib/utils/datetime_utility'; import { format24HourTimeStringFromInt, formatDate } from '~/lib/utils/datetime_utility';
import { s__, __ } from '~/locale'; import { s__, __ } from '~/locale';
import AddEditRotationForm from './add_edit_rotation_form.vue'; import AddEditRotationForm from './add_edit_rotation_form.vue';
...@@ -47,14 +47,15 @@ export default { ...@@ -47,14 +47,15 @@ export default {
}, },
apollo: { apollo: {
participants: { participants: {
query: usersSearchQuery, query: searchProjectMembersQuery,
variables() { variables() {
return { return {
fullPath: this.projectPath,
search: this.ptSearchTerm, search: this.ptSearchTerm,
}; };
}, },
update({ users: { nodes = [] } = {} }) { update({ project: { projectMembers: { nodes = [] } = {} } = {} } = {}) {
return nodes; return nodes.map(({ user }) => ({ ...user }));
}, },
error(error) { error(error) {
this.error = error; this.error = error;
......
...@@ -79,7 +79,7 @@ export default { ...@@ -79,7 +79,7 @@ export default {
:view-only="true" :view-only="true"
> >
<div class="gl-display-flex gl-text-white gl-font-weight-normal"> <div class="gl-display-flex gl-text-white gl-font-weight-normal">
<gl-avatar :src="assignee.avatarUrl" :size="16" /> <gl-avatar :src="assignee.user.avatarUrl" :size="16" />
<span v-if="!rotationMobileView" class="gl-ml-2" data-testid="rotation-assignee-name">{{ <span v-if="!rotationMobileView" class="gl-ml-2" data-testid="rotation-assignee-name">{{
assigneeName assigneeName
}}</span> }}</span>
......
...@@ -26,7 +26,8 @@ ...@@ -26,7 +26,8 @@
"colorPalette": "blue", "colorPalette": "blue",
"user": { "user": {
"id": "1", "id": "1",
"username": "nora.schaden" "username": "nora.schaden",
"avatarUrl": "/url"
} }
}, },
"startsAt": "2021-01-12T10:04:56.333Z", "startsAt": "2021-01-12T10:04:56.333Z",
...@@ -39,7 +40,8 @@ ...@@ -39,7 +40,8 @@
"colorPalette": "orange", "colorPalette": "orange",
"user": { "user": {
"id": "2", "id": "2",
"username": "racheal.loving" "username": "racheal.loving",
"avatarUrl": "/url"
} }
}, },
"startsAt": "2021-01-16T10:04:56.333Z", "startsAt": "2021-01-16T10:04:56.333Z",
......
...@@ -10,7 +10,7 @@ import getOncallSchedulesWithRotationsQuery from 'ee/oncall_schedules/graphql/qu ...@@ -10,7 +10,7 @@ import getOncallSchedulesWithRotationsQuery from 'ee/oncall_schedules/graphql/qu
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import createFlash, { FLASH_TYPES } from '~/flash'; import createFlash, { FLASH_TYPES } from '~/flash';
import usersSearchQuery from '~/graphql_shared/queries/users_search.query.graphql'; import searchProjectMembersQuery from '~/graphql_shared/queries/project_user_members_search.query.graphql';
import { import {
participants, participants,
getOncallSchedulesQueryResponse, getOncallSchedulesQueryResponse,
...@@ -84,7 +84,7 @@ describe('AddEditRotationModal', () => { ...@@ -84,7 +84,7 @@ describe('AddEditRotationModal', () => {
getOncallSchedulesWithRotationsQuery, getOncallSchedulesWithRotationsQuery,
jest.fn().mockResolvedValue(getOncallSchedulesQueryResponse), jest.fn().mockResolvedValue(getOncallSchedulesQueryResponse),
], ],
[usersSearchQuery, userSearchQueryHandler], [searchProjectMembersQuery, userSearchQueryHandler],
[createOncallScheduleRotationMutation, createRotationHandler], [createOncallScheduleRotationMutation, createRotationHandler],
]); ]);
...@@ -158,7 +158,7 @@ describe('AddEditRotationModal', () => { ...@@ -158,7 +158,7 @@ describe('AddEditRotationModal', () => {
}); });
describe('with mocked Apollo client', () => { describe('with mocked Apollo client', () => {
it('it calls searchUsers query with the search parameter', async () => { it('it calls the `searchProjectMembersQuery` query with the search parameter and project path', async () => {
userSearchQueryHandler = jest.fn().mockResolvedValue({ userSearchQueryHandler = jest.fn().mockResolvedValue({
data: { data: {
users: { users: {
...@@ -168,7 +168,10 @@ describe('AddEditRotationModal', () => { ...@@ -168,7 +168,10 @@ describe('AddEditRotationModal', () => {
}); });
createComponentWithApollo({ search: 'root' }); createComponentWithApollo({ search: 'root' });
await awaitApolloDomMock(); await awaitApolloDomMock();
expect(userSearchQueryHandler).toHaveBeenCalledWith({ search: 'root' }); expect(userSearchQueryHandler).toHaveBeenCalledWith({
search: 'root',
fullPath: projectPath,
});
}); });
it('calls a mutation with correct parameters and creates a rotation', async () => { it('calls a mutation with correct parameters and creates a rotation', async () => {
......
...@@ -28,7 +28,7 @@ describe('RotationAssignee', () => { ...@@ -28,7 +28,7 @@ describe('RotationAssignee', () => {
wrapper = extendedWrapper( wrapper = extendedWrapper(
shallowMount(RotationAssignee, { shallowMount(RotationAssignee, {
propsData: { propsData: {
assignee: { avatarUrl: '/url', ...assignee.participant }, assignee: { ...assignee.participant },
rotationAssigneeStartsAt: assignee.startsAt, rotationAssigneeStartsAt: assignee.startsAt,
rotationAssigneeEndsAt: assignee.endsAt, rotationAssigneeEndsAt: assignee.endsAt,
rotationAssigneeStyle: { left: '0px', width: `${shiftWidth}px` }, rotationAssigneeStyle: { left: '0px', width: `${shiftWidth}px` },
...@@ -49,7 +49,7 @@ describe('RotationAssignee', () => { ...@@ -49,7 +49,7 @@ describe('RotationAssignee', () => {
describe('rotation assignee token', () => { describe('rotation assignee token', () => {
it('should render an assignee name and avatar', () => { it('should render an assignee name and avatar', () => {
expect(findAvatar().props('src')).toBe(wrapper.vm.assignee.avatarUrl); expect(findAvatar().props('src')).toBe(assignee.participant.user.avatarUrl);
expect(findName().text()).toBe(assignee.participant.user.username); expect(findName().text()).toBe(assignee.participant.user.username);
}); });
......
...@@ -90,13 +90,11 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders ...@@ -90,13 +90,11 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
<div <div
class="gl-display-flex gl-text-white gl-font-weight-normal" class="gl-display-flex gl-text-white gl-font-weight-normal"
> >
<div <img
class="gl-avatar gl-avatar-identicon gl-avatar-circle gl-avatar-s16 gl-avatar-identicon-bg1" alt="avatar"
> class="gl-avatar gl-avatar-circle gl-avatar-s16"
src="/url"
/>
</div>
<!----> <!---->
</div> </div>
...@@ -138,13 +136,11 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders ...@@ -138,13 +136,11 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
<div <div
class="gl-display-flex gl-text-white gl-font-weight-normal" class="gl-display-flex gl-text-white gl-font-weight-normal"
> >
<div <img
class="gl-avatar gl-avatar-identicon gl-avatar-circle gl-avatar-s16 gl-avatar-identicon-bg1" alt="avatar"
> class="gl-avatar gl-avatar-circle gl-avatar-s16"
src="/url"
/>
</div>
<!----> <!---->
</div> </div>
......
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