Merge branch '9703-track-clicks-on-the-issue-sidebars' into 'master'
Backport: Resolve "Track clicks on the issue sidebars" See merge request gitlab-org/gitlab-ce!31435
This commit is contained in:
commit
2ef59c7e4b
12 changed files with 82 additions and 8 deletions
2
app/assets/javascripts/event_tracking/issue_sidebar.js
Normal file
2
app/assets/javascripts/event_tracking/issue_sidebar.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
export const initSidebarTracking = () => {};
|
||||
export const trackEvent = () => {};
|
|
@ -1,4 +1,5 @@
|
|||
import Vue from 'vue';
|
||||
import { initSidebarTracking } from 'ee_else_ce/event_tracking/issue_sidebar';
|
||||
import issuableApp from './components/app.vue';
|
||||
import { parseIssuableData } from './utils/parse_data';
|
||||
import '../vue_shared/vue_resource_interceptor';
|
||||
|
@ -9,6 +10,9 @@ export default function initIssueableApp() {
|
|||
components: {
|
||||
issuableApp,
|
||||
},
|
||||
mounted() {
|
||||
initSidebarTracking();
|
||||
},
|
||||
render(createElement) {
|
||||
return createElement('issuable-app', {
|
||||
props: parseIssuableData(),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { n__ } from '~/locale';
|
||||
import { trackEvent } from 'ee_else_ce/event_tracking/issue_sidebar';
|
||||
|
||||
export default {
|
||||
name: 'AssigneeTitle',
|
||||
|
@ -29,13 +30,23 @@ export default {
|
|||
return n__('Assignee', `%d Assignees`, assignees);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
trackEdit() {
|
||||
trackEvent('click_edit_button', 'assignee');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div class="title hide-collapsed">
|
||||
{{ assigneeTitle }}
|
||||
<i v-if="loading" aria-hidden="true" class="fa fa-spinner fa-spin block-loading"></i>
|
||||
<a v-if="editable" class="js-sidebar-dropdown-toggle edit-link float-right" href="#">
|
||||
<a
|
||||
v-if="editable"
|
||||
class="js-sidebar-dropdown-toggle edit-link float-right"
|
||||
href="#"
|
||||
@click.prevent="trackEdit"
|
||||
>
|
||||
{{ __('Edit') }}
|
||||
</a>
|
||||
<a
|
||||
|
|
|
@ -5,6 +5,7 @@ import tooltip from '~/vue_shared/directives/tooltip';
|
|||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import eventHub from '~/sidebar/event_hub';
|
||||
import editForm from './edit_form.vue';
|
||||
import { trackEvent } from 'ee_else_ce/event_tracking/issue_sidebar';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -51,6 +52,11 @@ export default {
|
|||
toggleForm() {
|
||||
this.edit = !this.edit;
|
||||
},
|
||||
onEditClick() {
|
||||
this.toggleForm();
|
||||
|
||||
trackEvent('click_edit_button', 'confidentiality');
|
||||
},
|
||||
updateConfidentialAttribute(confidential) {
|
||||
this.service
|
||||
.update('issue', { confidential })
|
||||
|
@ -82,7 +88,7 @@ export default {
|
|||
v-if="isEditable"
|
||||
class="float-right confidential-edit"
|
||||
href="#"
|
||||
@click.prevent="toggleForm"
|
||||
@click.prevent="onEditClick"
|
||||
>
|
||||
{{ __('Edit') }}
|
||||
</a>
|
||||
|
|
|
@ -6,6 +6,7 @@ import issuableMixin from '~/vue_shared/mixins/issuable';
|
|||
import Icon from '~/vue_shared/components/icon.vue';
|
||||
import eventHub from '~/sidebar/event_hub';
|
||||
import editForm from './edit_form.vue';
|
||||
import { trackEvent } from 'ee_else_ce/event_tracking/issue_sidebar';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -65,7 +66,11 @@ export default {
|
|||
toggleForm() {
|
||||
this.mediator.store.isLockDialogOpen = !this.mediator.store.isLockDialogOpen;
|
||||
},
|
||||
onEditClick() {
|
||||
this.toggleForm();
|
||||
|
||||
trackEvent('click_edit_button', 'lock_issue');
|
||||
},
|
||||
updateLockedAttribute(locked) {
|
||||
this.mediator.service
|
||||
.update(this.issuableType, {
|
||||
|
@ -109,7 +114,7 @@ export default {
|
|||
v-if="isEditable"
|
||||
class="float-right lock-edit"
|
||||
type="button"
|
||||
@click.prevent="toggleForm"
|
||||
@click.prevent="onEditClick"
|
||||
>
|
||||
{{ __('Edit') }}
|
||||
</button>
|
||||
|
|
|
@ -4,6 +4,7 @@ import icon from '~/vue_shared/components/icon.vue';
|
|||
import toggleButton from '~/vue_shared/components/toggle_button.vue';
|
||||
import tooltip from '~/vue_shared/directives/tooltip';
|
||||
import eventHub from '../../event_hub';
|
||||
import { trackEvent } from 'ee_else_ce/event_tracking/issue_sidebar';
|
||||
|
||||
const ICON_ON = 'notifications';
|
||||
const ICON_OFF = 'notifications-off';
|
||||
|
@ -63,6 +64,8 @@ export default {
|
|||
|
||||
// Component event emission.
|
||||
this.$emit('toggleSubscription', this.id);
|
||||
|
||||
trackEvent('toggle_button', 'notifications', this.subscribed ? 0 : 1);
|
||||
},
|
||||
onClickCollapsedIcon() {
|
||||
this.$emit('toggleSidebar');
|
||||
|
|
|
@ -405,7 +405,11 @@ module IssuablesHelper
|
|||
placement: is_collapsed ? 'left' : nil,
|
||||
container: is_collapsed ? 'body' : nil,
|
||||
boundary: 'viewport',
|
||||
is_collapsed: is_collapsed
|
||||
is_collapsed: is_collapsed,
|
||||
track_label: "right_sidebar",
|
||||
track_property: "update_todo",
|
||||
track_event: "click_button",
|
||||
track_value: ""
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
= _('Milestone')
|
||||
= icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
|
||||
- if can_edit_issuable
|
||||
= link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right'
|
||||
= link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right', data: { track_label: "right_sidebar", track_property: "milestone", track_event: "click_edit_button", track_value: "" }
|
||||
.value.hide-collapsed
|
||||
- if milestone.present?
|
||||
= link_to milestone[:title], milestone[:web_url], class: "bold has-tooltip", title: sidebar_milestone_remaining_days(milestone), data: { container: "body", html: 'true', boundary: 'viewport' }
|
||||
|
@ -66,7 +66,7 @@
|
|||
= _('Due date')
|
||||
= icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
|
||||
- if can_edit_issuable
|
||||
= link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right'
|
||||
= link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right', data: { track_label: "right_sidebar", track_property: "due_date", track_event: "click_edit_button", track_value: "" }
|
||||
.value.hide-collapsed
|
||||
%span.value-content
|
||||
- if issuable_sidebar[:due_date]
|
||||
|
@ -102,7 +102,7 @@
|
|||
= _('Labels')
|
||||
= icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
|
||||
- if can_edit_issuable
|
||||
= link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link qa-edit-link-labels float-right'
|
||||
= link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link qa-edit-link-labels float-right', data: { track_label: "right_sidebar", track_property: "labels", track_event: "click_edit_button", track_value: "" }
|
||||
.value.issuable-show-labels.dont-hide.hide-collapsed.qa-labels-block{ class: ("has-labels" if selected_labels.any?) }
|
||||
- if selected_labels.any?
|
||||
- selected_labels.each do |label_hash|
|
||||
|
@ -160,7 +160,7 @@
|
|||
= custom_icon('icon_arrow_right')
|
||||
.dropdown.sidebar-move-issue-dropdown.hide-collapsed
|
||||
%button.btn.btn-default.btn-block.js-sidebar-dropdown-toggle.js-move-issue{ type: 'button',
|
||||
data: { toggle: 'dropdown', display: 'static' } }
|
||||
data: { toggle: 'dropdown', display: 'static', track_label: "right_sidebar", track_property: "move_issue", track_event: "click_button", track_value: "" } }
|
||||
= _('Move issue')
|
||||
.dropdown-menu.dropdown-menu-selectable.dropdown-extended-height
|
||||
= dropdown_title(_('Move issue'))
|
||||
|
|
|
@ -4,8 +4,10 @@ import AssigneeTitle from '~/sidebar/components/assignees/assignee_title.vue';
|
|||
describe('AssigneeTitle component', () => {
|
||||
let component;
|
||||
let AssigneeTitleComponent;
|
||||
let statsSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
statsSpy = spyOnDependency(AssigneeTitle, 'trackEvent');
|
||||
AssigneeTitleComponent = Vue.extend(AssigneeTitle);
|
||||
});
|
||||
|
||||
|
@ -102,4 +104,16 @@ describe('AssigneeTitle component', () => {
|
|||
|
||||
expect(component.$el.querySelector('.edit-link')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('calls trackEvent when edit is clicked', () => {
|
||||
component = new AssigneeTitleComponent({
|
||||
propsData: {
|
||||
numberOfAssignees: 0,
|
||||
editable: true,
|
||||
},
|
||||
}).$mount();
|
||||
component.$el.querySelector('.js-sidebar-dropdown-toggle').click();
|
||||
|
||||
expect(statsSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,8 +4,10 @@ import confidentialIssueSidebar from '~/sidebar/components/confidential/confiden
|
|||
describe('Confidential Issue Sidebar Block', () => {
|
||||
let vm1;
|
||||
let vm2;
|
||||
let statsSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
statsSpy = spyOnDependency(confidentialIssueSidebar, 'trackEvent');
|
||||
const Component = Vue.extend(confidentialIssueSidebar);
|
||||
const service = {
|
||||
update: () => Promise.resolve(true),
|
||||
|
@ -67,4 +69,10 @@ describe('Confidential Issue Sidebar Block', () => {
|
|||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('calls trackEvent when "Edit" is clicked', () => {
|
||||
vm1.$el.querySelector('.confidential-edit').click();
|
||||
|
||||
expect(statsSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,8 +4,10 @@ import lockIssueSidebar from '~/sidebar/components/lock/lock_issue_sidebar.vue';
|
|||
describe('LockIssueSidebar', () => {
|
||||
let vm1;
|
||||
let vm2;
|
||||
let statsSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
statsSpy = spyOnDependency(lockIssueSidebar, 'trackEvent');
|
||||
const Component = Vue.extend(lockIssueSidebar);
|
||||
|
||||
const mediator = {
|
||||
|
@ -59,6 +61,12 @@ describe('LockIssueSidebar', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('calls trackEvent when "Edit" is clicked', () => {
|
||||
vm1.$el.querySelector('.lock-edit').click();
|
||||
|
||||
expect(statsSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('displays the edit form when opened from collapsed state', done => {
|
||||
expect(vm1.isLockDialogOpen).toBe(false);
|
||||
|
||||
|
|
|
@ -6,8 +6,10 @@ import mountComponent from 'spec/helpers/vue_mount_component_helper';
|
|||
describe('Subscriptions', function() {
|
||||
let vm;
|
||||
let Subscriptions;
|
||||
let statsSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
statsSpy = spyOnDependency(subscriptions, 'trackEvent');
|
||||
Subscriptions = Vue.extend(subscriptions);
|
||||
});
|
||||
|
||||
|
@ -58,6 +60,13 @@ describe('Subscriptions', function() {
|
|||
expect(vm.$emit).toHaveBeenCalledWith('toggleSubscription', jasmine.any(Object));
|
||||
});
|
||||
|
||||
it('calls trackEvent when toggled', () => {
|
||||
vm = mountComponent(Subscriptions, { subscribed: true });
|
||||
vm.toggleSubscription();
|
||||
|
||||
expect(statsSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('onClickCollapsedIcon method emits `toggleSidebar` event on component', () => {
|
||||
vm = mountComponent(Subscriptions, { subscribed: true });
|
||||
spyOn(vm, '$emit');
|
||||
|
|
Loading…
Reference in a new issue