Skip to content
代码片段 群组 项目
提交 eb01d7be 编辑于 作者: anna_vovchenko's avatar anna_vovchenko 提交者: Ezekiel Kigbo
浏览文件

Added Snowplow events to the Clusters page

The events are added for:
- changing the tab
- Agent registration modal process

Changelog: added
上级 fec794ba
No related branches found
No related tags found
无相关合并请求
<script>
import { GlTabs, GlTab } from '@gitlab/ui';
import { CLUSTERS_TABS, MAX_CLUSTERS_LIST, MAX_LIST_COUNT, AGENT } from '../constants';
import Tracking from '~/tracking';
import {
CLUSTERS_TABS,
MAX_CLUSTERS_LIST,
MAX_LIST_COUNT,
AGENT,
EVENT_LABEL_TABS,
EVENT_ACTIONS,
} from '../constants';
import Agents from './agents.vue';
import InstallAgentModal from './install_agent_modal.vue';
import ClustersActions from './clusters_actions.vue';
import Clusters from './clusters.vue';
import ClustersViewAll from './clusters_view_all.vue';
const trackingMixin = Tracking.mixin({ label: EVENT_LABEL_TABS });
export default {
components: {
GlTabs,
......@@ -18,6 +28,7 @@ export default {
InstallAgentModal,
},
CLUSTERS_TABS,
mixins: [trackingMixin],
props: {
defaultBranchName: {
default: '.noBranch',
......@@ -34,9 +45,12 @@ export default {
methods: {
onTabChange(tabName) {
this.selectedTabIndex = CLUSTERS_TABS.findIndex((tab) => tab.queryParamValue === tabName);
this.maxAgents = tabName === AGENT ? MAX_LIST_COUNT : MAX_CLUSTERS_LIST;
},
trackTabChange(tab) {
const tabName = CLUSTERS_TABS[tab].queryParamValue;
this.track(EVENT_ACTIONS.change_tab, { property: tabName });
},
},
};
</script>
......@@ -47,6 +61,7 @@ export default {
sync-active-tab-with-query-params
nav-class="gl-flex-grow-1 gl-align-items-center"
lazy
@input="trackTabChange"
>
<gl-tab
v-for="(tab, idx) in $options.CLUSTERS_TABS"
......
......@@ -11,8 +11,15 @@ import {
import { helpPagePath } from '~/helpers/help_page_helper';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import CodeBlock from '~/vue_shared/components/code_block.vue';
import Tracking from '~/tracking';
import { generateAgentRegistrationCommand } from '../clusters_util';
import { INSTALL_AGENT_MODAL_ID, I18N_AGENT_MODAL, KAS_DISABLED_ERROR } from '../constants';
import {
INSTALL_AGENT_MODAL_ID,
I18N_AGENT_MODAL,
KAS_DISABLED_ERROR,
EVENT_LABEL_MODAL,
EVENT_ACTIONS,
} from '../constants';
import { addAgentToStore, addAgentConfigToStore } from '../graphql/cache_update';
import createAgent from '../graphql/mutations/create_agent.mutation.graphql';
import createAgentToken from '../graphql/mutations/create_agent_token.mutation.graphql';
......@@ -20,8 +27,12 @@ import getAgentsQuery from '../graphql/queries/get_agents.query.graphql';
import agentConfigurations from '../graphql/queries/agent_configurations.query.graphql';
import AvailableAgentsDropdown from './available_agents_dropdown.vue';
const trackingMixin = Tracking.mixin({ label: EVENT_LABEL_MODAL });
export default {
modalId: INSTALL_AGENT_MODAL_ID,
EVENT_ACTIONS,
EVENT_LABEL_MODAL,
components: {
AvailableAgentsDropdown,
ClipboardButton,
......@@ -34,6 +45,7 @@ export default {
GlModal,
GlSprintf,
},
mixins: [trackingMixin],
inject: ['projectPath', 'kasAddress', 'emptyStateImage'],
props: {
defaultBranchName: {
......@@ -81,7 +93,7 @@ export default {
return !this.registering && this.agentName !== null;
},
canCancel() {
return !this.registered && !this.registering && this.isRegisterModal;
return !this.registered && !this.registering && this.isAgentRegistrationModal;
},
agentRegistrationCommand() {
return generateAgentRegistrationCommand(this.agentToken, this.kasAddress);
......@@ -117,21 +129,24 @@ export default {
return `/${this.projectPath}`;
},
modalType() {
return !this.availableAgents?.length && !this.registered ? 'install' : 'register';
return !this.availableAgents?.length && !this.registered
? 'empty_state'
: 'agent_registration';
},
modalSize() {
return this.isInstallModal ? 'sm' : 'md';
return this.isEmptyStateModal ? 'sm' : 'md';
},
isInstallModal() {
return this.modalType === 'install';
isEmptyStateModal() {
return this.modalType === 'empty_state';
},
isRegisterModal() {
return this.modalType === 'register';
isAgentRegistrationModal() {
return this.modalType === 'agent_registration';
},
},
methods: {
setAgentName(name) {
this.agentName = name;
this.track(EVENT_ACTIONS.select);
},
closeModal() {
this.$refs.modal.hide();
......@@ -242,8 +257,9 @@ export default {
static
lazy
@hidden="resetModal"
@show="track($options.EVENT_ACTIONS.open, { property: modalType })"
>
<template v-if="isRegisterModal">
<template v-if="isAgentRegistrationModal">
<template v-if="!registered">
<p>
<strong>{{ i18n.selectAgentTitle }}</strong>
......@@ -347,23 +363,40 @@ export default {
</template>
<template #modal-footer>
<gl-button v-if="canCancel" @click="closeModal">{{ i18n.cancel }} </gl-button>
<gl-button
v-if="canCancel"
:data-track-action="$options.EVENT_ACTIONS.click"
:data-track-label="$options.EVENT_LABEL_MODAL"
data-track-property="cancel"
@click="closeModal"
>{{ i18n.cancel }}
</gl-button>
<gl-button v-if="registered" variant="confirm" category="primary" @click="closeModal"
<gl-button
v-if="registered"
variant="confirm"
category="primary"
:data-track-action="$options.EVENT_ACTIONS.click"
:data-track-label="$options.EVENT_LABEL_MODAL"
data-track-property="close"
@click="closeModal"
>{{ i18n.close }}
</gl-button>
<gl-button
v-else-if="isRegisterModal"
v-else-if="isAgentRegistrationModal"
:disabled="!nextButtonDisabled"
variant="confirm"
category="primary"
:data-track-action="$options.EVENT_ACTIONS.click"
:data-track-label="$options.EVENT_LABEL_MODAL"
data-track-property="register"
@click="registerAgent"
>{{ i18n.registerAgentButton }}
</gl-button>
<gl-button
v-if="isInstallModal"
v-if="isEmptyStateModal"
:href="repositoryPath"
variant="confirm"
category="secondary"
......@@ -371,7 +404,14 @@ export default {
>{{ i18n.secondaryButton }}
</gl-button>
<gl-button v-if="isInstallModal" variant="confirm" category="primary" @click="closeModal"
<gl-button
v-if="isEmptyStateModal"
variant="confirm"
category="primary"
:data-track-action="$options.EVENT_ACTIONS.click"
:data-track-label="$options.EVENT_LABEL_MODAL"
data-track-property="done"
@click="closeModal"
>{{ i18n.done }}
</gl-button>
</template>
......
......@@ -65,7 +65,7 @@ export const STATUSES = {
};
export const I18N_AGENT_MODAL = {
register: {
agent_registration: {
registerAgentButton: s__('ClusterAgents|Register Agent'),
close: __('Close'),
cancel: __('Cancel'),
......@@ -104,7 +104,7 @@ export const I18N_AGENT_MODAL = {
registrationErrorTitle: __('Failed to register Agent'),
unknownError: s__('ClusterAgents|An unknown error occurred. Please try again.'),
},
install: {
empty_state: {
modalTitle: s__('ClusterAgents|Install new Agent'),
modalBody: s__(
'ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process.',
......@@ -236,3 +236,12 @@ export const CLUSTERS_ACTIONS = {
export const AGENT = 'agent';
export const CERTIFICATE_BASED = 'certificate_based';
export const EVENT_LABEL_MODAL = 'agent_registration_modal';
export const EVENT_LABEL_TABS = 'kubernetes_section_tabs';
export const EVENT_ACTIONS = {
open: 'open_modal',
select: 'select_agent',
click: 'click_button',
change_tab: 'change_tab',
};
import { GlTabs, GlTab } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { mockTracking } from 'helpers/tracking_helper';
import ClustersMainView from '~/clusters_list/components/clusters_main_view.vue';
import InstallAgentModal from '~/clusters_list/components/install_agent_modal.vue';
import {
......@@ -8,12 +9,15 @@ import {
CLUSTERS_TABS,
MAX_CLUSTERS_LIST,
MAX_LIST_COUNT,
EVENT_LABEL_TABS,
EVENT_ACTIONS,
} from '~/clusters_list/constants';
const defaultBranchName = 'default-branch';
describe('ClustersMainViewComponent', () => {
let wrapper;
let trackingSpy;
const propsData = {
defaultBranchName,
......@@ -23,6 +27,7 @@ describe('ClustersMainViewComponent', () => {
wrapper = shallowMountExtended(ClustersMainView, {
propsData,
});
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
afterEach(() => {
......@@ -71,6 +76,7 @@ describe('ClustersMainViewComponent', () => {
beforeEach(() => {
findComponent().vm.$emit('changeTab', AGENT);
});
it('changes the tab', () => {
expect(findTabs().attributes('value')).toBe('1');
});
......@@ -78,5 +84,13 @@ describe('ClustersMainViewComponent', () => {
it('passes correct max-agents param to the modal', () => {
expect(findModal().props('maxAgents')).toBe(MAX_LIST_COUNT);
});
it('sends the correct tracking event', () => {
findTabs().vm.$emit('input', 1);
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS.change_tab, {
label: EVENT_LABEL_TABS,
property: AGENT,
});
});
});
});
......@@ -2,9 +2,15 @@ import { GlAlert, GlButton, GlFormInputGroup } from '@gitlab/ui';
import { createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { mockTracking } from 'helpers/tracking_helper';
import AvailableAgentsDropdown from '~/clusters_list/components/available_agents_dropdown.vue';
import InstallAgentModal from '~/clusters_list/components/install_agent_modal.vue';
import { I18N_AGENT_MODAL, MAX_LIST_COUNT } from '~/clusters_list/constants';
import {
I18N_AGENT_MODAL,
MAX_LIST_COUNT,
EVENT_LABEL_MODAL,
EVENT_ACTIONS,
} from '~/clusters_list/constants';
import getAgentsQuery from '~/clusters_list/graphql/queries/get_agents.query.graphql';
import getAgentConfigurations from '~/clusters_list/graphql/queries/agent_configurations.query.graphql';
import createAgentMutation from '~/clusters_list/graphql/mutations/create_agent.mutation.graphql';
......@@ -34,6 +40,7 @@ const maxAgents = MAX_LIST_COUNT;
describe('InstallAgentModal', () => {
let wrapper;
let apolloProvider;
let trackingSpy;
const configurations = [{ agentName: 'agent-name' }];
const apolloQueryResponse = {
......@@ -56,7 +63,7 @@ describe('InstallAgentModal', () => {
const findActionButton = () => findButtonByVariant('confirm');
const findCancelButton = () => findButtonByVariant('default');
const findSecondaryButton = () => wrapper.findByTestId('agent-secondary-button');
const findImage = () => wrapper.findByRole('img', { alt: I18N_AGENT_MODAL.install.altText });
const findImage = () => wrapper.findByRole('img', { alt: I18N_AGENT_MODAL.empty_state.altText });
const expectDisabledAttribute = (element, disabled) => {
if (disabled) {
......@@ -121,6 +128,7 @@ describe('InstallAgentModal', () => {
[getAgentConfigurations, jest.fn().mockResolvedValue(apolloQueryResponse)],
]);
createWrapper();
trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
afterEach(() => {
......@@ -129,7 +137,7 @@ describe('InstallAgentModal', () => {
});
describe('when agent configurations are present', () => {
const i18n = I18N_AGENT_MODAL.register;
const i18n = I18N_AGENT_MODAL.agent_registration;
describe('initial state', () => {
it('renders the dropdown for available agents', () => {
......@@ -150,6 +158,14 @@ describe('InstallAgentModal', () => {
expect(findActionButton().text()).toBe(i18n.registerAgentButton);
expectDisabledAttribute(findActionButton(), true);
});
it('sends the event with the modalType', () => {
findModal().vm.$emit('show');
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS.open, {
label: EVENT_LABEL_MODAL,
property: 'agent_registration',
});
});
});
describe('an agent is selected', () => {
......@@ -161,6 +177,12 @@ describe('InstallAgentModal', () => {
expect(findActionButton().isVisible()).toBe(true);
expectDisabledAttribute(findActionButton(), false);
});
it('sends the correct tracking event', () => {
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS.select, {
label: EVENT_LABEL_MODAL,
});
});
});
describe('registering an agent', () => {
......@@ -247,7 +269,7 @@ describe('InstallAgentModal', () => {
});
describe('when there are no agent configurations present', () => {
const i18n = I18N_AGENT_MODAL.install;
const i18n = I18N_AGENT_MODAL.empty_state;
const apolloQueryEmptyResponse = {
data: {
project: {
......@@ -272,5 +294,13 @@ describe('InstallAgentModal', () => {
expect(findSecondaryButton().isVisible()).toBe(true);
expect(findSecondaryButton().text()).toBe(i18n.secondaryButton);
});
it('sends the event with the modalType', () => {
findModal().vm.$emit('show');
expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS.open, {
label: EVENT_LABEL_MODAL,
property: 'empty_state',
});
});
});
});
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册