Commit 84755869 authored by Doug Stull's avatar Doug Stull

Add source to invite modal calls

- for telemetry of who triggered an invite.
parent 43239d5a
......@@ -29,8 +29,7 @@ export default {
},
triggerSource: {
type: String,
required: false,
default: 'unknown',
required: true,
},
trackExperiment: {
type: String,
......
......@@ -248,7 +248,7 @@ export default {
>
<template #footer>
<gl-dropdown-item v-if="directlyInviteMembers">
<sidebar-invite-members />
<sidebar-invite-members :issuable-type="issuableType" />
</gl-dropdown-item> </template
></user-select>
</template>
......
......@@ -9,6 +9,17 @@ export default {
components: {
InviteMembersTrigger,
},
props: {
issuableType: {
type: String,
required: true,
},
},
computed: {
triggerSource() {
return `${this.issuableType}-assignee-dropdown`;
},
},
};
</script>
......@@ -18,6 +29,7 @@ export default {
:display-text="$options.displayText"
:event="$options.dataTrackEvent"
:label="$options.dataTrackLabel"
:trigger-source="triggerSource"
classes="gl-display-block gl-pl-6 gl-hover-text-decoration-none gl-hover-text-blue-800!"
/>
</template>
......@@ -15,7 +15,10 @@
.gl-w-half.gl-xs-w-full
.gl-display-flex.gl-flex-wrap.gl-justify-content-end.gl-mb-3
.js-invite-group-trigger{ data: { classes: 'gl-mt-3 gl-sm-w-auto gl-w-full', display_text: _('Invite a group') } }
.js-invite-members-trigger{ data: { variant: 'success', classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3', display_text: _('Invite members') } }
.js-invite-members-trigger{ data: { variant: 'success',
classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3',
trigger_source: 'group-members-page',
display_text: _('Invite members') } }
= render 'groups/invite_members_modal', group: @group
- if can_manage_members? && Feature.disabled?(:invite_members_group_modal, @group)
%hr.gl-mt-4
......
......@@ -26,7 +26,10 @@
- if @project.allowed_to_share_with_group?
.js-invite-group-trigger{ data: { classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3', display_text: _('Invite a group') } }
- if can_manage_project_members?(@project) && !membership_locked?
.js-invite-members-trigger{ data: { variant: 'success', classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3', display_text: _('Invite members') } }
.js-invite-members-trigger{ data: { variant: 'success',
classes: 'gl-mt-3 gl-sm-w-auto gl-w-full gl-sm-ml-3',
trigger_source: 'project-members-page',
display_text: _('Invite members') } }
= render 'projects/invite_members_modal', project: @project
- else
......
......@@ -45,4 +45,5 @@
= render 'shared/issuable/sidebar_user_dropdown',
options: options,
wrapper_class: 'js-sidebar-assignee-dropdown',
track_label: 'edit_assignee'
track_label: 'edit_assignee',
trigger_source: "#{issuable_type}-assignee-dropdown"
......@@ -42,4 +42,5 @@
= render 'shared/issuable/sidebar_user_dropdown',
options: options,
wrapper_class: 'js-sidebar-reviewer-dropdown',
track_label: 'edit_reviewer'
track_label: 'edit_reviewer',
trigger_source: "#{issuable_type}-reviewer-dropdown"
......@@ -15,6 +15,7 @@
.js-invite-members-trigger{ data: { trigger_element: 'anchor',
display_text: _('Invite Members'),
event: 'click_invite_members',
trigger_source: local_assigns.fetch(:trigger_source),
label: data['track-label'] } }
- else
= dropdown_tag(data['dropdown-title'], options: options)
......@@ -23,7 +23,7 @@ module API
requires :email, types: [String, Array[String]], email_or_email_list: true, desc: 'The email address to invite, or multiple emails separated by comma'
requires :access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'A valid access level (defaults: `30`, developer access level)'
optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
optional :invite_source, type: String, desc: 'Source that triggered the member creation process', default: 'api'
optional :invite_source, type: String, desc: 'Source that triggered the member creation process', default: 'invitations-api'
end
post ":id/invitations" do
params[:source] = find_source(source_type, params[:id])
......
......@@ -93,7 +93,7 @@ module API
requires :access_level, type: Integer, desc: 'A valid access level (defaults: `30`, developer access level)'
requires :user_id, types: [Integer, String], desc: 'The user ID of the new member or multiple IDs separated by commas.'
optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
optional :invite_source, type: String, desc: 'Source that triggered the member creation process', default: 'api'
optional :invite_source, type: String, desc: 'Source that triggered the member creation process', default: 'members-api'
end
# rubocop: disable CodeReuse/ActiveRecord
post ":id/members" do
......
......@@ -80,7 +80,7 @@ RSpec.describe 'Groups > Members > Manage members' do
expect_snowplow_event(
category: 'Members::CreateService',
action: 'create_member',
label: 'unknown',
label: 'group-members-page',
property: 'existing_user',
user: user1
)
......@@ -189,7 +189,7 @@ RSpec.describe 'Groups > Members > Manage members' do
expect_snowplow_event(
category: 'Members::InviteService',
action: 'create_member',
label: 'unknown',
label: 'group-members-page',
property: 'net_new_user',
user: user1
)
......
......@@ -59,7 +59,7 @@ RSpec.describe 'Project members list', :js do
expect_snowplow_event(
category: 'Members::CreateService',
action: 'create_member',
label: 'unknown',
label: 'project-members-page',
property: 'existing_user',
user: user1
)
......@@ -117,7 +117,7 @@ RSpec.describe 'Project members list', :js do
expect_snowplow_event(
category: 'Members::InviteService',
action: 'create_member',
label: 'unknown',
label: 'project-members-page',
property: 'net_new_user',
user: user1
)
......
......@@ -7,6 +7,8 @@ import eventHub from '~/invite_members/event_hub';
jest.mock('~/experimentation/experiment_tracking');
const displayText = 'Invite team members';
const triggerSource = '_trigger_source_';
let wrapper;
let triggerProps;
let findButton;
......@@ -26,7 +28,7 @@ const createComponent = (props = {}) => {
};
describe.each(['button', 'anchor'])('with triggerElement as %s', (triggerElement) => {
triggerProps = { triggerElement };
triggerProps = { triggerElement, triggerSource };
findButton = () => wrapper.findComponent(triggerComponent[triggerElement]);
afterEach(() => {
......@@ -48,22 +50,14 @@ describe.each(['button', 'anchor'])('with triggerElement as %s', (triggerElement
spy = jest.spyOn(eventHub, '$emit');
});
it('emits openModal from an unknown source', () => {
createComponent();
findButton().vm.$emit('click');
expect(spy).toHaveBeenCalledWith('openModal', { inviteeType: 'members', source: 'unknown' });
});
it('emits openModal from a named source', () => {
createComponent({ triggerSource: '_trigger_source_' });
createComponent();
findButton().vm.$emit('click');
expect(spy).toHaveBeenCalledWith('openModal', {
inviteeType: 'members',
source: '_trigger_source_',
source: triggerSource,
});
});
});
......
......@@ -4,11 +4,16 @@ import SidebarInviteMembers from '~/sidebar/components/assignees/sidebar_invite_
describe('Sidebar invite members component', () => {
let wrapper;
const issuableType = 'issue';
const findDirectInviteLink = () => wrapper.findComponent(InviteMembersTrigger);
const createComponent = () => {
wrapper = shallowMount(SidebarInviteMembers);
wrapper = shallowMount(SidebarInviteMembers, {
propsData: {
issuableType,
},
});
};
afterEach(() => {
......@@ -23,5 +28,9 @@ describe('Sidebar invite members component', () => {
it('renders a direct link to project members path', () => {
expect(findDirectInviteLink().exists()).toBe(true);
});
it('has expected attributes on the trigger', () => {
expect(findDirectInviteLink().props('triggerSource')).toBe('issue-assignee-dropdown');
});
});
});
......@@ -161,7 +161,7 @@ RSpec.describe API::Invitations do
expect_snowplow_event(
category: 'Members::InviteService',
action: 'create_member',
label: 'api',
label: 'invitations-api',
property: 'net_new_user',
user: maintainer
)
......
......@@ -265,7 +265,7 @@ RSpec.describe API::Members do
expect_snowplow_event(
category: 'Members::CreateService',
action: 'create_member',
label: 'api',
label: 'members-api',
property: 'existing_user',
user: maintainer
)
......@@ -322,7 +322,7 @@ RSpec.describe API::Members do
expect_snowplow_event(
category: 'Members::CreateService',
action: 'create_member',
label: 'api',
label: 'members-api',
property: 'existing_user',
user: maintainer
)
......
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