diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-03 00:10:55 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-03 00:10:55 +0000 |
commit | 198460d5879a516844f81f667c6bc4fe84ed1719 (patch) | |
tree | cd6e50aec1232500dc4486adf2cb8dd28c8ac378 /app | |
parent | 9579eee8954e0405c2dadb19c2a73c9597ce37ea (diff) | |
download | gitlab-ce-198460d5879a516844f81f667c6bc4fe84ed1719.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
26 files changed, 212 insertions, 79 deletions
diff --git a/app/assets/javascripts/frequent_items/components/app.vue b/app/assets/javascripts/frequent_items/components/app.vue index a4e883c96b5..947d3053094 100644 --- a/app/assets/javascripts/frequent_items/components/app.vue +++ b/app/assets/javascripts/frequent_items/components/app.vue @@ -6,6 +6,7 @@ import { mapVuexModuleActions, mapVuexModuleGetters, } from '~/lib/utils/vuex_module_mappers'; +import Tracking from '~/tracking'; import { FREQUENT_ITEMS, STORAGE_KEY } from '../constants'; import eventHub from '../event_hub'; import { isMobile, updateExistingFrequentItem, sanitizeItem } from '../utils'; @@ -13,6 +14,8 @@ import FrequentItemsList from './frequent_items_list.vue'; import frequentItemsMixin from './frequent_items_mixin'; import FrequentItemsSearchInput from './frequent_items_search_input.vue'; +const trackingMixin = Tracking.mixin(); + export default { components: { FrequentItemsSearchInput, @@ -24,7 +27,7 @@ export default { directives: { GlTooltip: GlTooltipDirective, }, - mixins: [frequentItemsMixin], + mixins: [frequentItemsMixin, trackingMixin], inject: ['vuexModule'], props: { currentUserName: { @@ -84,6 +87,13 @@ export default { 'toggleItemsListEditablity', 'fetchFrequentItems', ]), + toggleItemsListEditablityTracked() { + this.track('click_button', { + label: 'toggle_edit_frequent_items', + property: 'navigation_top', + }); + this.toggleItemsListEditablity(); + }, dropdownOpenHandler() { if (this.searchQuery === '' || isMobile()) { this.fetchFrequentItems(); @@ -155,7 +165,7 @@ export default { :title="translations.headerEditToggle" :class="{ 'gl-bg-gray-100!': isItemsListEditable }" class="gl-p-2!" - @click="toggleItemsListEditablity" + @click="toggleItemsListEditablityTracked" > <gl-icon name="pencil" :class="{ 'gl-text-gray-900!': isItemsListEditable }" /> </gl-button> diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue index 430498e7194..056dedf8757 100644 --- a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue +++ b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue @@ -64,6 +64,13 @@ export default { }, }, methods: { + removeFrequentItemTracked(item) { + this.track('click_button', { + label: `${this.dropdownType}_dropdown_remove_frequent_item`, + property: 'navigation_top', + }); + this.removeFrequentItem(item); + }, ...mapVuexModuleActions((vm) => vm.vuexModule, ['removeFrequentItem']), }, }; @@ -77,7 +84,7 @@ export default { class="gl-text-left gl-w-full" button-text-classes="gl-display-flex gl-w-full" data-testid="frequent-item-link" - @click="track('click_link', { label: itemTrackingLabel })" + @click="track('click_link', { label: itemTrackingLabel, property: 'navigation_top' })" > <div class="gl-flex-grow-1"> <project-avatar @@ -117,7 +124,7 @@ export default { :title="__('Remove')" class="gl-align-self-center gl-p-1! gl-absolute! gl-w-auto! gl-right-4 gl-top-half gl-translate-y-n50" data-testid="item-remove" - @click.stop.prevent="removeFrequentItem(itemId)" + @click.stop.prevent="removeFrequentItemTracked(itemId)" > <gl-icon name="close" /> </gl-button> diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue index 4a1b7e57749..023245f050b 100644 --- a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue +++ b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue @@ -28,12 +28,25 @@ export default { searchQuery: debounce(function debounceSearchQuery() { this.track('type_search_query', { label: `${this.dropdownType}_dropdown_frequent_items_search_input`, + property: 'navigation_top', }); this.setSearchQuery(this.searchQuery); }, 500), }, methods: { ...mapVuexModuleActions((vm) => vm.vuexModule, ['setSearchQuery']), + trackFocus() { + this.track('focus_input', { + label: `${this.dropdownType}_dropdown_frequent_items_search_input`, + property: 'navigation_top', + }); + }, + trackBlur() { + this.track('blur_input', { + label: `${this.dropdownType}_dropdown_frequent_items_search_input`, + property: 'navigation_top', + }); + }, }, }; </script> @@ -43,6 +56,8 @@ export default { <gl-search-box-by-type v-model="searchQuery" :placeholder="translations.searchInputPlaceholder" + @focus="trackFocus" + @blur="trackBlur" /> </div> </template> diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js index f58781fa9ec..6c9354b663f 100644 --- a/app/assets/javascripts/header.js +++ b/app/assets/javascripts/header.js @@ -33,6 +33,13 @@ function initStatusTriggers() { if (setStatusModalTriggerEl) { setStatusModalTriggerEl.addEventListener('click', () => { + const topNavbar = document.querySelector('.navbar-gitlab'); + const buttonWithinTopNav = topNavbar && topNavbar.contains(setStatusModalTriggerEl); + Tracking.event(undefined, 'click_button', { + label: 'user_edit_status', + property: buttonWithinTopNav ? 'navigation_top' : undefined, + }); + import( /* webpackChunkName: 'statusModalBundle' */ './set_status_modal/set_status_modal_wrapper.vue' ) diff --git a/app/assets/javascripts/header_search/components/app.vue b/app/assets/javascripts/header_search/components/app.vue index bf5daf29b21..ace0d77c431 100644 --- a/app/assets/javascripts/header_search/components/app.vue +++ b/app/assets/javascripts/header_search/components/app.vue @@ -171,7 +171,7 @@ export default { Tracking.event(undefined, 'focus_input', { label: 'global_search', - property: 'top_navigation', + property: 'navigation_top', }); } }, @@ -190,7 +190,7 @@ export default { Tracking.event(undefined, 'blur_input', { label: 'global_search', - property: 'top_navigation', + property: 'navigation_top', }); }, 200); }, diff --git a/app/assets/javascripts/nav/components/new_nav_toggle.vue b/app/assets/javascripts/nav/components/new_nav_toggle.vue index 7b0076cc5d4..da22a8d2fb7 100644 --- a/app/assets/javascripts/nav/components/new_nav_toggle.vue +++ b/app/assets/javascripts/nav/components/new_nav_toggle.vue @@ -45,7 +45,7 @@ export default { Tracking.event(undefined, 'click_toggle', { label: this.enabled ? 'disable_new_nav_beta' : 'enable_new_nav_beta', - property: 'navigation', + property: this.enabled ? 'navigation' : 'navigation_top', }); window.location.reload(); diff --git a/app/assets/javascripts/nav/components/top_nav_app.vue b/app/assets/javascripts/nav/components/top_nav_app.vue index e55bf25a60c..ab9313f7041 100644 --- a/app/assets/javascripts/nav/components/top_nav_app.vue +++ b/app/assets/javascripts/nav/components/top_nav_app.vue @@ -24,7 +24,7 @@ export default { trackToggleEvent() { Tracking.event(undefined, 'click_nav', { label: 'hamburger_menu', - property: 'top_navigation', + property: 'navigation_top', }); }, }, diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue index a04b082fa87..4b65d6fd9ac 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals.vue @@ -62,6 +62,7 @@ export default { fetchingApprovals: true, hasApprovalAuthError: false, isApproving: false, + updatedCount: 0, }; }, computed: { @@ -197,6 +198,7 @@ export default { return serviceFn() .then((data) => { this.mr.setApprovals(data); + this.updatedCount += 1; if (!window.gon?.features?.realtimeMrStatusChange) { eventHub.$emit('MRWidgetUpdateRequested'); @@ -250,10 +252,10 @@ export default { /> <approvals-summary v-else - :approved="isApproved" - :approvals-left="approvals.approvals_left || 0" - :rules-left="approvals.approvalRuleNamesLeft" - :approvers="approvedBy" + :project-path="mr.targetProjectFullPath" + :iid="`${mr.iid}`" + :updated-count="updatedCount" + :multiple-approval-rules-available="mr.multipleApprovalRulesAvailable" /> </div> <div v-if="hasInvalidRules" class="gl-text-gray-400 gl-mt-2" data-testid="invalid-rules"> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue index d7255eb6ad2..7c283c42a03 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue @@ -1,4 +1,5 @@ <script> +import { GlSkeletonLoader } from '@gitlab/ui'; import { toNounSeriesText } from '~/lib/utils/grammar'; import { n__, sprintf } from '~/locale'; import { @@ -7,32 +8,68 @@ import { APPROVED_BY_OTHERS, } from '~/vue_merge_request_widget/components/approvals/messages'; import UserAvatarList from '~/vue_shared/components/user_avatar/user_avatar_list.vue'; +import { getIdFromGraphQLId } from '~/graphql_shared/utils'; +import { getApprovalRuleNamesLeft } from 'ee_else_ce/vue_merge_request_widget/mappers'; +import approvedByQuery from 'ee_else_ce/vue_merge_request_widget/components/approvals/queries/approved_by.query.graphql'; export default { + apollo: { + approvalState: { + query: approvedByQuery, + variables() { + return { + projectPath: this.projectPath, + iid: this.iid, + }; + }, + update: (data) => data.project.mergeRequest, + }, + }, components: { + GlSkeletonLoader, UserAvatarList, }, props: { - approved: { - type: Boolean, + projectPath: { + type: String, required: true, }, - approvalsLeft: { - type: Number, + iid: { + type: String, required: true, }, - rulesLeft: { - type: Array, + updatedCount: { + type: Number, required: false, - default: () => [], + default: 0, }, - approvers: { - type: Array, + multipleApprovalRulesAvailable: { + type: Boolean, required: false, - default: () => [], + default: false, }, }, + data() { + return { + approvalState: {}, + }; + }, computed: { + approvers() { + return this.approvalState.approvedBy?.nodes || []; + }, + approved() { + return this.approvalState.approved || this.approvalState.approvedBy?.nodes.length > 0; + }, + approvalsLeft() { + return this.approvalState.approvalsLeft || 0; + }, + rulesLeft() { + return getApprovalRuleNamesLeft( + this.multipleApprovalRulesAvailable, + (this.approvalState.approvalState?.rules || []).filter((r) => r.approvalsRequired !== 0), + ); + }, approvalLeftMessage() { if (this.rulesLeft.length) { return sprintf( @@ -81,32 +118,53 @@ export default { if (!this.currentUserId) { return false; } - return this.approvers.some((approver) => approver.id === this.currentUserId); + return this.approvers.some( + (approver) => getIdFromGraphQLId(approver.id) === this.currentUserId, + ); }, approvedByOthers() { if (!this.currentUserId) { return false; } - return this.approvers.some((approver) => approver.id !== this.currentUserId); + return this.approvers.some( + (approver) => getIdFromGraphQLId(approver.id) !== this.currentUserId, + ); }, currentUserId() { return gon.current_user_id; }, }, + watch: { + updatedCount() { + this.$apollo.queries.approvalState.refetch(); + }, + }, }; </script> <template> <div data-qa-selector="approvals_summary_content"> - <span class="gl-font-weight-bold">{{ approvalLeftMessage }}</span> - <template v-if="hasApprovers"> - <span v-if="approvalLeftMessage">{{ message }}</span> - <span v-else class="gl-font-weight-bold">{{ message }}</span> - <user-avatar-list - class="gl-display-inline-block gl-vertical-align-middle gl-pt-1" - :img-size="24" - :items="approvers" - /> + <div + v-if="$apollo.queries.approvalState.loading" + class="gl-display-inline-block gl-vertical-align-middle" + style="width: 132px; height: 24px" + > + <gl-skeleton-loader :width="132" :height="24"> + <rect width="100" height="24" x="0" y="0" rx="4" /> + <circle cx="120" cy="12" r="12" /> + </gl-skeleton-loader> + </div> + <template v-else> + <span class="gl-font-weight-bold">{{ approvalLeftMessage }}</span> + <template v-if="hasApprovers"> + <span v-if="approvalLeftMessage">{{ message }}</span> + <span v-else class="gl-font-weight-bold">{{ message }}</span> + <user-avatar-list + class="gl-display-inline-block gl-vertical-align-middle gl-pt-1" + :img-size="24" + :items="approvers" + /> + </template> </template> </div> </template> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/queries/approved_by.query.graphql b/app/assets/javascripts/vue_merge_request_widget/components/approvals/queries/approved_by.query.graphql new file mode 100644 index 00000000000..c8cae6a8885 --- /dev/null +++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/queries/approved_by.query.graphql @@ -0,0 +1,16 @@ +query approvedBy($projectPath: ID!, $iid: String!) { + project(fullPath: $projectPath) { + id + mergeRequest(iid: $iid) { + id + approvedBy { + nodes { + id + name + avatarUrl + webUrl + } + } + } + } +} diff --git a/app/assets/javascripts/vue_merge_request_widget/mappers.js b/app/assets/javascripts/vue_merge_request_widget/mappers.js new file mode 100644 index 00000000000..63c4c3dc871 --- /dev/null +++ b/app/assets/javascripts/vue_merge_request_widget/mappers.js @@ -0,0 +1,3 @@ +export function getApprovalRuleNamesLeft(_, rules) { + return rules; +} diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js index 85df2ea63c8..f6a7ef58c10 100644 --- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js +++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js @@ -30,6 +30,7 @@ export default class MergeRequestStore { this.machineValue = this.stateMachine.value; this.mergeDetailsCollapsed = window.innerWidth < 768; this.mergeError = data.mergeError; + this.multipleApprovalRulesAvailable = data.multiple_approval_rules_available || false; this.id = data.id; this.setPaths(data); diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_list.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_list.vue index 231f5ff3d1f..4f3b482d7f8 100644 --- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_list.vue +++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_list.vue @@ -75,7 +75,7 @@ export default { v-for="item in visibleItems" :key="item.id" :link-href="item.web_url" - :img-src="item.avatar_url" + :img-src="item.avatar_url || item.avatarUrl" :img-alt="item.name" :tooltip-text="item.name" :img-size="imgSize" diff --git a/app/assets/javascripts/whats_new/components/app.vue b/app/assets/javascripts/whats_new/components/app.vue index 9e5361e8302..472bc1dfacc 100644 --- a/app/assets/javascripts/whats_new/components/app.vue +++ b/app/assets/javascripts/whats_new/components/app.vue @@ -35,7 +35,11 @@ export default { const body = document.querySelector('body'); const { namespaceId } = body.dataset; - this.track('click_whats_new_drawer', { label: 'namespace_id', value: namespaceId }); + this.track('click_whats_new_drawer', { + label: 'namespace_id', + value: namespaceId, + property: 'navigation_top', + }); }, methods: { ...mapActions(['openDrawer', 'closeDrawer', 'fetchItems', 'setDrawerBodyHeight']), diff --git a/app/helpers/nav/new_dropdown_helper.rb b/app/helpers/nav/new_dropdown_helper.rb index 4972d359bd6..ddd6469a9e4 100644 --- a/app/helpers/nav/new_dropdown_helper.rb +++ b/app/helpers/nav/new_dropdown_helper.rb @@ -32,7 +32,7 @@ module Nav id: 'new_project', title: _('New project/repository'), href: new_project_path(namespace_id: group.id), - data: { track_action: 'click_link_new_project_group', track_label: 'plus_menu_dropdown' } + data: { track_action: 'click_link_new_project_group', track_label: 'plus_menu_dropdown', track_property: 'navigation_top' } ) ) end @@ -43,7 +43,7 @@ module Nav id: 'new_subgroup', title: _('New subgroup'), href: new_group_path(parent_id: group.id, anchor: 'create-group-pane'), - data: { track_action: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' } + data: { track_action: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown', track_property: 'navigation_top' } ) ) end @@ -74,7 +74,7 @@ module Nav id: 'new_issue', title: _('New issue'), href: new_project_issue_path(project), - data: { track_action: 'click_link_new_issue', track_label: 'plus_menu_dropdown', qa_selector: 'new_issue_link' } + data: { track_action: 'click_link_new_issue', track_label: 'plus_menu_dropdown', track_property: 'navigation_top', qa_selector: 'new_issue_link' } ) ) end @@ -85,7 +85,7 @@ module Nav id: 'new_mr', title: _('New merge request'), href: project_new_merge_request_path(merge_project), - data: { track_action: 'click_link_new_mr', track_label: 'plus_menu_dropdown' } + data: { track_action: 'click_link_new_mr', track_label: 'plus_menu_dropdown', track_property: 'navigation_top' } ) ) end @@ -96,7 +96,7 @@ module Nav id: 'new_snippet', title: _('New snippet'), href: new_project_snippet_path(project), - data: { track_action: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown' } + data: { track_action: 'click_link_new_snippet_project', track_label: 'plus_menu_dropdown', track_property: 'navigation_top' } ) ) end @@ -124,7 +124,7 @@ module Nav id: 'general_new_project', title: _('New project/repository'), href: new_project_path, - data: { track_action: 'click_link_new_project', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_project_link' } + data: { track_action: 'click_link_new_project', track_label: 'plus_menu_dropdown', track_property: 'navigation_top', qa_selector: 'global_new_project_link' } ) ) end @@ -135,7 +135,7 @@ module Nav id: 'general_new_group', title: _('New group'), href: new_group_path, - data: { track_action: 'click_link_new_group', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_group_link' } + data: { track_action: 'click_link_new_group', track_label: 'plus_menu_dropdown', track_property: 'navigation_top', qa_selector: 'global_new_group_link' } ) ) end @@ -146,7 +146,7 @@ module Nav id: 'general_new_snippet', title: _('New snippet'), href: new_snippet_path, - data: { track_action: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown', qa_selector: 'global_new_snippet_link' } + data: { track_action: 'click_link_new_snippet_parent', track_label: 'plus_menu_dropdown', track_property: 'navigation_top', qa_selector: 'global_new_snippet_link' } ) ) end @@ -165,7 +165,8 @@ module Nav href: href, data: { track_action: 'click_link_invite_members', - track_label: 'plus_menu_dropdown' + track_label: 'plus_menu_dropdown', + track_property: 'navigation_top' } ) end diff --git a/app/helpers/nav/top_nav_helper.rb b/app/helpers/nav/top_nav_helper.rb index bd4d661ab49..fb11c183aeb 100644 --- a/app/helpers/nav/top_nav_helper.rb +++ b/app/helpers/nav/top_nav_helper.rb @@ -101,7 +101,7 @@ module Nav builder.add_primary_menu_item_with_shortcut( header: top_nav_localized_headers[:switch_to], active: nav == 'project' || active_nav_link?(path: %w[root#index projects#trending projects#starred dashboard/projects#index]), - data: { track_label: "projects_dropdown", track_action: "click_dropdown", qa_selector: "projects_dropdown" }, + data: { track_label: "projects_dropdown", track_action: "click_dropdown", track_property: "navigation_top", qa_selector: "projects_dropdown" }, view: PROJECTS_VIEW, shortcut_href: dashboard_projects_path, **projects_menu_item_attrs @@ -115,7 +115,7 @@ module Nav builder.add_primary_menu_item_with_shortcut( header: top_nav_localized_headers[:switch_to], active: nav == 'group' || active_nav_link?(path: %w[dashboard/groups explore/groups]), - data: { track_label: "groups_dropdown", track_action: "click_dropdown", qa_selector: "groups_dropdown" }, + data: { track_label: "groups_dropdown", track_action: "click_dropdown", track_property: "navigation_top", qa_selector: "groups_dropdown" }, view: GROUPS_VIEW, shortcut_href: dashboard_groups_path, **groups_menu_item_attrs @@ -233,7 +233,7 @@ module Nav tracking_attrs( "menu_#{label.underscore.parameterize(separator: '_')}", 'click_dropdown', - 'navigation' + 'navigation_top' )[:data] || {} end diff --git a/app/models/concerns/vulnerability_finding_helpers.rb b/app/models/concerns/vulnerability_finding_helpers.rb index b5d48260072..1e8a290c050 100644 --- a/app/models/concerns/vulnerability_finding_helpers.rb +++ b/app/models/concerns/vulnerability_finding_helpers.rb @@ -49,7 +49,7 @@ module VulnerabilityFindingHelpers finding_data = report_finding.to_hash.except(:compare_key, :identifiers, :location, :scanner, :links, :signatures, :flags, :evidence) - identifiers = report_finding.identifiers.map do |identifier| + identifiers = report_finding.identifiers.uniq(&:fingerprint).map do |identifier| Vulnerabilities::Identifier.new(identifier.to_hash.merge({ project: project })) end signatures = report_finding.signatures.map do |signature| diff --git a/app/models/packages/package.rb b/app/models/packages/package.rb index c6e8ff6c3fa..c5da647eea5 100644 --- a/app/models/packages/package.rb +++ b/app/models/packages/package.rb @@ -279,6 +279,7 @@ class Packages::Package < ApplicationRecord project.packages .preload_pipelines .including_tags + .displayable .with_name(name) .where.not(version: version) .with_package_type(package_type) diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml index 8363d424c1b..af27026845e 100644 --- a/app/views/layouts/header/_current_user_dropdown.html.haml +++ b/app/views/layouts/header/_current_user_dropdown.html.haml @@ -3,7 +3,7 @@ %ul %li.current-user - if current_user_menu?(:profile) - = link_to current_user, class: 'gl-line-height-20!', data: { user: current_user.username, testid: 'user-profile-link', qa_selector: 'user_profile_link' } do + = link_to current_user, class: 'gl-line-height-20!', data: { user: current_user.username, testid: 'user-profile-link', track_action: "click_link", track_label: "user_profile", track_property: "navigation_top", qa_selector: 'user_profile_link' } do = render 'layouts/header/current_user_dropdown_item' - else .gl-py-3.gl-px-4 @@ -23,28 +23,28 @@ = emoji_icon('rocket') - if current_user_menu?(:settings) %li - = link_to s_("CurrentUser|Edit profile"), profile_path, data: { qa_selector: 'edit_profile_link' } + = link_to s_("CurrentUser|Edit profile"), profile_path, data: { qa_selector: 'edit_profile_link', track_action: "click_link", track_label: "user_edit_profile", track_property: "navigation_top" } %li - = link_to s_("CurrentUser|Preferences"), profile_preferences_path + = link_to s_("CurrentUser|Preferences"), profile_preferences_path, data: { track_action: "click_link", track_label: "user_preferences", track_property: "navigation_top" } = render_if_exists 'layouts/header/buy_pipeline_minutes', project: @project, namespace: @group - if current_user_menu?(:help) %li.divider.d-md-none %li.d-md-none - = link_to _("Help"), help_path + = link_to _("Help"), help_path, data: {track_action: 'click_link', track_label: 'help', track_property: 'navigation_top'} %li.d-md-none - = link_to _("Support"), support_url + = link_to _("Support"), support_url, data: {track_action: 'click_link', track_label: 'support', track_property: 'navigation_top'} %li.d-md-none = render 'shared/help_dropdown_forum_link' %li.d-md-none - = link_to _("Submit feedback"), Gitlab::Utils.append_path(promo_url, "submit-feedback") + = link_to _("Submit feedback"), Gitlab::Utils.append_path(promo_url, "submit-feedback"), data: {track_action: 'click_link', track_label: 'submit_feedback', track_property: 'navigation_top'} - if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile) %li.d-md-none = render 'shared/user_dropdown_contributing_link' = render 'shared/user_dropdown_instance_review' - if Gitlab.com_but_not_canary? %li.d-md-none - = link_to _("Switch to GitLab Next"), Gitlab::Saas.canary_toggle_com_url + = link_to _("Switch to GitLab Next"), Gitlab::Saas.canary_toggle_com_url, data: { track_action: "click_link", track_label: "switch_to_canary", track_property: "navigation_top" } - if Feature.enabled?(:super_sidebar_nav, current_user) %li.divider @@ -53,4 +53,4 @@ - if current_user_menu?(:sign_out) %li.divider %li - = link_to _("Sign out"), destroy_user_session_path, method: :post, class: "sign-out-link", data: { qa_selector: 'sign_out_link' } + = link_to _("Sign out"), destroy_user_session_path, method: :post, class: "sign-out-link", data: { qa_selector: 'sign_out_link', track_action: "click_link", track_label: "user_sign_out", track_property: "navigation_top" } diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 4cd876e4fc0..3b2cd4c30dd 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -8,7 +8,7 @@ .title-container.hide-when-top-nav-responsive-open.gl-transition-medium.gl-display-flex.gl-align-items-stretch.gl-pt-0.gl-mr-3 .title %span.gl-sr-only GitLab - = link_to root_path, title: _('Dashboard'), id: 'logo', class: 'has-tooltip', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation') do + = link_to root_path, title: _('Dashboard'), id: 'logo', class: 'has-tooltip', **tracking_attrs('main_navigation', 'click_gitlab_logo_link', 'navigation_top') do = brand_header_logo .gl-display-flex.gl-align-items-center - if Gitlab.com_and_canary? @@ -36,7 +36,11 @@ - else = render 'layouts/search' %li.nav-item{ class: 'd-none d-sm-inline-block d-lg-none' } - = link_to search_menu_item.fetch(:href), title: search_menu_item.fetch(:title), aria: { label: search_menu_item.fetch(:title) }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do + = link_to search_menu_item.fetch(:href), title: search_menu_item.fetch(:title), aria: { label: search_menu_item.fetch(:title) }, + data: { toggle: 'tooltip', placement: 'bottom', container: 'body', + track_action: 'click_link', + track_label: 'global_search', + track_property: 'navigation_top' } do = sprite_icon(search_menu_item.fetch(:icon)) .navbar-collapse.gl-transition-medium.collapse @@ -49,7 +53,7 @@ data: { qa_selector: 'issues_shortcut_button', toggle: 'tooltip', placement: 'bottom', track_label: 'main_navigation', track_action: 'click_issues_link', - track_property: 'navigation', + track_property: 'navigation_top', container: 'body' } do = sprite_icon('issues') - issues_count = assigned_issuables_count(:issues) @@ -62,9 +66,9 @@ data: { qa_selector: 'merge_requests_shortcut_button', toggle: "dropdown", placement: 'bottom', - track_label: 'main_navigation', - track_action: 'click_merge_link', - track_property: 'navigation', + track_label: 'merge_requests_menu', + track_action: 'click_dropdown', + track_property: 'navigation_top', container: 'body' } do = sprite_icon('git-merge') = gl_badge_tag({ size: :sm, variant: :warning }, { class: "js-merge-requests-count gl-ml-n2 #{'gl-display-none' if user_merge_requests_counts[:total] == 0}", "aria-label": n_("%d merge request", "%d merge requests", user_merge_requests_counts[:total]) % user_merge_requests_counts[:total] }) do @@ -75,12 +79,16 @@ %li.dropdown-header = _('Merge requests') %li - = link_to assigned_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center js-prefetch-document' do + = link_to assigned_mrs_dashboard_path, + class: 'gl-display-flex! gl-align-items-center js-prefetch-document', + data: {track_action: 'click_link', track_label: 'merge_requests_assigned', track_property: 'navigation_top'} do = _('Assigned') = gl_badge_tag({ variant: :neutral, size: :sm }, { class: "js-assigned-mr-count gl-ml-auto" }) do = user_merge_requests_counts[:assigned] %li - = link_to reviewer_mrs_dashboard_path, class: 'dashboard-shortcuts-review_requests gl-display-flex! gl-align-items-center js-prefetch-document' do + = link_to reviewer_mrs_dashboard_path, + class: 'dashboard-shortcuts-review_requests gl-display-flex! gl-align-items-center js-prefetch-document', + data: {track_action: 'click_link', track_label: 'merge_requests_to_review', track_property: 'navigation_top'} do = _('Review requests') = gl_badge_tag({ variant: :neutral, size: :sm }, { class: "js-reviewer-mr-count gl-ml-auto" }) do = user_merge_requests_counts[:review_requested] @@ -90,15 +98,15 @@ data: { qa_selector: 'todos_shortcut_button', toggle: 'tooltip', placement: 'bottom', track_label: 'main_navigation', track_action: 'click_to_do_link', - track_property: 'navigation', + track_property: 'navigation_top', container: 'body' } do = sprite_icon('todo-done') -# The todos' counter badge's visibility is being toggled by adding or removing the .hidden class in Js. -# We'll eventually migrate to .gl-display-none: https://gitlab.com/gitlab-org/gitlab/-/issues/351792. = gl_badge_tag({ size: :sm, variant: :info }, { class: "js-todos-count gl-ml-n2 #{'hidden' if todos_pending_count == 0}", "aria-label": _("Todos count") }) do = todos_count_format(todos_pending_count) - %li.nav-item.header-help.dropdown.d-none.d-md-block{ data: { track_action: 'click_question_mark_link', track_label: 'main_navigation', track_property: 'navigation', track_experiment: 'cross_stage_fdm' } } - = link_to help_path, class: 'header-help-dropdown-toggle gl-relative', data: { toggle: "dropdown" } do + %li.nav-item.header-help.dropdown.d-none.d-md-block + = link_to help_path, class: 'header-help-dropdown-toggle gl-relative', data: { toggle: "dropdown", track_action: 'click_question_mark_link', track_label: 'main_navigation', track_property: 'navigation_top', track_experiment: 'cross_stage_fdm' } do %span.gl-sr-only = s_('Nav|Help') = sprite_icon('question-o') @@ -110,8 +118,8 @@ %li.nav-item.gl-display-none.gl-sm-display-block = render "layouts/nav/top_nav" - if header_link?(:user_dropdown) - %li.nav-item.header-user.js-nav-user-dropdown.dropdown{ data: { track_label: "profile_dropdown", track_action: "click_dropdown", track_value: "", qa_selector: 'user_menu', testid: 'user-menu' }, class: ('mr-0' if has_impersonation_link) } - = link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do + %li.nav-item.header-user.js-nav-user-dropdown.dropdown{ data: { qa_selector: 'user_menu', testid: 'user-menu' }, class: ('mr-0' if has_impersonation_link) } + = link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown", track_label: "profile_dropdown", track_action: "click_dropdown", track_property: "navigation_top" } do = render Pajamas::AvatarComponent.new(current_user, size: 24, class: 'header-user-avatar', avatar_options: { data: { qa_selector: 'user_avatar_content' } }) = render_if_exists 'layouts/header/user_notification_dot', project: project, namespace: group = sprite_icon('chevron-down', css_class: 'caret-down') diff --git a/app/views/layouts/header/_gitlab_version.html.haml b/app/views/layouts/header/_gitlab_version.html.haml index 581d4d498e1..22771ac09c9 100644 --- a/app/views/layouts/header/_gitlab_version.html.haml +++ b/app/views/layouts/header/_gitlab_version.html.haml @@ -7,7 +7,7 @@ testid: 'gitlab-version-container', track_action: 'click_link', track_label: 'version_help_dropdown', - track_property: "#{Gitlab.version_info.major}.#{Gitlab.version_info.minor}" + track_property: 'navigation_top' } } %span diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml index bdd1ae291fd..f50df72afbc 100644 --- a/app/views/layouts/header/_help_dropdown.html.haml +++ b/app/views/layouts/header/_help_dropdown.html.haml @@ -5,22 +5,22 @@ = render_if_exists 'layouts/header/help_dropdown/cross_stage_fdm' = render 'layouts/header/whats_new_dropdown_item' %li - = link_to _("Help"), help_path + = link_to _("Help"), help_path, data: {track_action: 'click_link', track_label: 'help', track_property: 'navigation_top'} %li - = link_to _("Support"), support_url + = link_to _("Support"), support_url, data: {track_action: 'click_link', track_label: 'support', track_property: 'navigation_top'} %li = render 'shared/help_dropdown_forum_link' %li - %button.js-shortcuts-modal-trigger{ type: "button" } + %button.js-shortcuts-modal-trigger{ type: "button", data: {track_action: 'click_button', track_label: 'keyboard_shortcuts_help', track_property: 'navigation_top'} } = _("Keyboard shortcuts") %kbd.flat.float-right{ "aria-hidden": "true" }= '?'.html_safe %li.divider %li - = link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback" + = link_to _("Submit feedback"), "https://about.gitlab.com/submit-feedback", data: {track_action: 'click_link', track_label: 'submit_feedback', track_property: 'navigation_top'} - if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile) %li = render 'shared/user_dropdown_contributing_link' = render 'shared/user_dropdown_instance_review' - if Gitlab.com_but_not_canary? %li - = link_to _("Switch to GitLab Next"), Gitlab::Saas.canary_toggle_com_url + = link_to _("Switch to GitLab Next"), Gitlab::Saas.canary_toggle_com_url, data: {track_action: 'click_link', track_label: 'gitlab_next', track_property: 'navigation_top'} diff --git a/app/views/layouts/header/_new_dropdown.html.haml b/app/views/layouts/header/_new_dropdown.html.haml index f39fb53032d..a135ee8fed8 100644 --- a/app/views/layouts/header/_new_dropdown.html.haml +++ b/app/views/layouts/header/_new_dropdown.html.haml @@ -6,7 +6,7 @@ - return if menu_sections.empty? -%li.header-new.gl-flex-grow-1.gl-flex-shrink-1.dropdown{ class: top_class, data: { track_label: "new_dropdown", track_action: "click_dropdown" } } +%li.header-new.gl-flex-grow-1.gl-flex-shrink-1.dropdown{ class: top_class, data: { track_label: "new_dropdown", track_action: "click_dropdown", track_property: "navigation_top" } } = link_to new_project_path, class: "header-new-dropdown-toggle has-tooltip gl-display-flex", id: "js-onboarding-new-project-link", title: title, ref: 'tooltip', aria: { label: title }, data: { toggle: 'dropdown', placement: 'bottom', container: 'body', display: 'static', qa_selector: 'new_menu_toggle' } do = sprite_icon('plus-square') = sprite_icon('chevron-down', css_class: 'caret-down') diff --git a/app/views/shared/_help_dropdown_forum_link.html.haml b/app/views/shared/_help_dropdown_forum_link.html.haml index 06889428e82..6d65f2e61bd 100644 --- a/app/views/shared/_help_dropdown_forum_link.html.haml +++ b/app/views/shared/_help_dropdown_forum_link.html.haml @@ -1,2 +1,2 @@ = link_to _("Community forum"), ApplicationHelper.community_forum, target: '_blank', class: 'text-nowrap', - rel: 'noopener noreferrer', data: { 'track_action': 'click_forum', 'track_property': 'question_menu' } + rel: 'noopener noreferrer', data: { 'track_action': 'click_link', 'track_label': 'community_forum', 'track_property': 'navigation_top' } diff --git a/app/views/shared/_user_dropdown_contributing_link.html.haml b/app/views/shared/_user_dropdown_contributing_link.html.haml index d4c3e11d051..70d9db998fc 100644 --- a/app/views/shared/_user_dropdown_contributing_link.html.haml +++ b/app/views/shared/_user_dropdown_contributing_link.html.haml @@ -1,2 +1,2 @@ -= link_to "https://about.gitlab.com/contributing", target: '_blank', class: 'text-nowrap' do += link_to "https://about.gitlab.com/contributing", target: '_blank', class: 'text-nowrap', data: {track_action: 'click_link', track_label: 'contribute_to_gitlab', track_property: 'navigation_top'} do = _("Contribute to GitLab") diff --git a/app/views/shared/_user_dropdown_instance_review.html.haml b/app/views/shared/_user_dropdown_instance_review.html.haml index 18bfb5d7e3e..1a02f9958b0 100644 --- a/app/views/shared/_user_dropdown_instance_review.html.haml +++ b/app/views/shared/_user_dropdown_instance_review.html.haml @@ -2,5 +2,5 @@ %li.divider %li - = link_to admin_instance_review_path, target: '_blank', class: 'text-nowrap' do + = link_to admin_instance_review_path, target: '_blank', class: 'text-nowrap', data: {track_action: 'click_link', track_label: 'instance_review', track_property: 'navigation_top'} do = _("Get a free instance review") |