Commit a6654f9c authored by Phil Hughes's avatar Phil Hughes

Merge branch '323757-add-invite-option-to-reviewer-dropdown' into 'master'

Add invite option to reviewer dropdown [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!62505
parents afd901f0 dfc2d7d8
......@@ -2,19 +2,21 @@ import Vue from 'vue';
import InviteMembersTrigger from '~/invite_members/components/invite_members_trigger.vue';
export default function initInviteMembersTrigger() {
const el = document.querySelector('.js-invite-members-trigger');
const triggers = document.querySelectorAll('.js-invite-members-trigger');
if (!el) {
if (!triggers) {
return false;
}
return new Vue({
el,
render: (createElement) =>
createElement(InviteMembersTrigger, {
props: {
...el.dataset,
},
}),
return triggers.forEach((el) => {
return new Vue({
el,
render: (createElement) =>
createElement(InviteMembersTrigger, {
props: {
...el.dataset,
},
}),
});
});
}
import loadAwardsHandler from '~/awards_handler';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import initIssuableSidebar from '~/init_issuable_sidebar';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import { IssuableType } from '~/issuable_show/constants';
import Issue from '~/issue';
import '~/notes/index';
......@@ -34,8 +32,6 @@ export default function initShowIssue() {
initIssueHeaderActions(store);
initSentryErrorStackTraceApp();
initRelatedMergeRequestsApp();
initInviteMembersModal();
initInviteMembersTrigger();
import(/* webpackChunkName: 'design_management' */ '~/design_management')
.then((module) => module.default())
......
......@@ -4,8 +4,6 @@ import loadAwardsHandler from '~/awards_handler';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import initPipelines from '~/commit/pipelines/pipelines_bundle';
import initIssuableSidebar from '~/init_issuable_sidebar';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import StatusBox from '~/issuable/components/status_box.vue';
import createDefaultClient from '~/lib/graphql';
import { handleLocationHash } from '~/lib/utils/common_utils';
......@@ -29,8 +27,6 @@ export default function initMergeRequestShow() {
} else {
loadAwardsHandler();
}
initInviteMembersModal();
initInviteMembersTrigger();
const el = document.querySelector('.js-mr-status-box');
const apolloProvider = new VueApollo({ defaultClient: createDefaultClient() });
......
......@@ -2,6 +2,8 @@ import $ from 'jquery';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createFlash from '~/flash';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
import { IssuableType } from '~/issue_show/constants';
import {
isInIssuePage,
......@@ -17,6 +19,7 @@ import SidebarDueDateWidget from '~/sidebar/components/date/sidebar_date_widget.
import SidebarParticipantsWidget from '~/sidebar/components/participants/sidebar_participants_widget.vue';
import SidebarReferenceWidget from '~/sidebar/components/reference/sidebar_reference_widget.vue';
import { apolloProvider } from '~/sidebar/graphql';
import trackShowInviteMemberLink from '~/sidebar/track_invite_members';
import Translate from '../vue_shared/translate';
import SidebarAssignees from './components/assignees/sidebar_assignees.vue';
import CopyEmailToClipboard from './components/copy_email_to_clipboard.vue';
......@@ -123,6 +126,12 @@ function mountAssigneesComponent() {
},
}),
});
const assigneeDropdown = document.querySelector('.js-sidebar-assignee-dropdown');
if (assigneeDropdown) {
trackShowInviteMemberLink(assigneeDropdown);
}
}
function mountReviewersComponent(mediator) {
......@@ -149,6 +158,12 @@ function mountReviewersComponent(mediator) {
},
}),
});
const reviewerDropdown = document.querySelector('.js-sidebar-reviewer-dropdown');
if (reviewerDropdown) {
trackShowInviteMemberLink(reviewerDropdown);
}
}
export function mountSidebarLabels() {
......@@ -438,6 +453,9 @@ const isAssigneesWidgetShown =
(isInIssuePage() || isInDesignPage()) && gon.features.issueAssigneesWidget;
export function mountSidebar(mediator) {
initInviteMembersModal();
initInviteMembersTrigger();
if (isAssigneesWidgetShown) {
mountAssigneesComponent();
} else {
......
import $ from 'jquery';
import Tracking from '~/tracking';
export default function initTrackInviteMembers(assigneeDropdown) {
const trackLabel = 'edit_assignee';
const { trackEvent } = assigneeDropdown.querySelector('.js-invite-members-track').dataset;
export default function initTrackInviteMembers(userDropdown) {
const { trackEvent, trackLabel } = userDropdown.querySelector('.js-invite-members-track').dataset;
$(assigneeDropdown).on('shown.bs.dropdown', () => {
$(userDropdown).on('shown.bs.dropdown', () => {
Tracking.event(undefined, trackEvent, {
label: trackLabel,
});
......
......@@ -42,22 +42,7 @@
- data['max-select'] = dropdown_options[:data][:'max-select'] if dropdown_options[:data][:'max-select']
- options[:data].merge!(data)
- if directly_invite_members?
- options[:dropdown_class] += ' dropdown-extended-height'
- options[:footer_content] = true
- options[:wrapper_class] = 'js-sidebar-assignee-dropdown'
- options[:toggle_class] += ' js-invite-members-track'
- data['track-event'] = 'show_invite_members'
- options[:data].merge!(data)
- invite_text = _('Invite Members')
- track_label = 'edit_assignee'
= dropdown_tag(title, options: options) do
%ul.dropdown-footer-list
%li
.js-invite-members-trigger{ data: { trigger_element: 'anchor',
display_text: invite_text,
event: 'click_invite_members',
label: track_label } }
- else
= dropdown_tag(title, options: options)
= render 'shared/issuable/sidebar_user_dropdown',
options: options,
wrapper_class: 'js-sidebar-assignee-dropdown',
track_label: 'edit_assignee'
......@@ -39,4 +39,7 @@
- data['max-select'] = dropdown_options[:data][:'max-select'] if dropdown_options[:data][:'max-select']
- options[:data].merge!(data)
= dropdown_tag(title, options: options)
= render 'shared/issuable/sidebar_user_dropdown',
options: options,
wrapper_class: 'js-sidebar-reviewer-dropdown',
track_label: 'edit_reviewer'
- options = local_assigns.fetch(:options)
- data = options[:data]
- if directly_invite_members?
- options[:dropdown_class] += ' dropdown-extended-height'
- options[:footer_content] = true
- options[:wrapper_class] = local_assigns.fetch(:wrapper_class)
- options[:toggle_class] += ' js-invite-members-track'
- data['track-event'] = 'show_invite_members'
- data['track-label'] = local_assigns.fetch(:track_label)
= dropdown_tag(data['dropdown-title'], options: options) do
%ul.dropdown-footer-list
%li
.js-invite-members-trigger{ data: { trigger_element: 'anchor',
display_text: _('Invite Members'),
event: 'click_invite_members',
label: data['track-label'] } }
- else
= dropdown_tag(data['dropdown-title'], options: options)
import trackShowInviteMemberLink from 'ee/projects/track_invite_members';
import initSidebarBundle from 'ee/sidebar/sidebar_bundle';
import initShow from '~/pages/projects/issues/show';
......@@ -13,7 +12,3 @@ initRelatedIssues();
new UserCallout({ className: 'js-epics-sidebar-callout' });
// eslint-disable-next-line no-new
new UserCallout({ className: 'js-weight-sidebar-callout' });
const assigneeDropdown = document.querySelector('.js-sidebar-assignee-dropdown');
if (assigneeDropdown) trackShowInviteMemberLink(assigneeDropdown);
import trackShowInviteMemberLink from 'ee/projects/track_invite_members';
import initSidebarBundle from 'ee/sidebar/sidebar_bundle';
import { initReviewBar } from '~/batch_comments';
import initMrNotes from '~/mr_notes';
......@@ -11,7 +10,3 @@ initSidebarBundle();
initMrNotes();
initReviewBar();
initIssuableHeaderWarning(store);
const assigneeDropdown = document.querySelector('.js-sidebar-assignee-dropdown');
if (assigneeDropdown) trackShowInviteMemberLink(assigneeDropdown);
......@@ -32,7 +32,7 @@ RSpec.describe 'Issue Sidebar' do
stub_feature_flags(issue_assignees_widget: false)
end
include_examples 'issuable invite members experiments' do
include_examples 'issuable invite members' do
let(:issuable_path) { project_issue_path(project, issue2) }
end
......
......@@ -68,14 +68,14 @@ RSpec.describe 'Merge request > User edits assignees sidebar', :js do
end
end
context 'with invite members experiment considerations' do
context 'with invite members considerations' do
let_it_be(:user) { create(:user) }
before do
sign_in(user)
end
include_examples 'issuable invite members experiments' do
include_examples 'issuable invite members' do
let(:issuable_path) { project_merge_request_path(project, merge_request) }
end
end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Merge request > User edits reviewers sidebar', :js do
context 'with invite members considerations' do
let_it_be(:merge_request) { create(:merge_request) }
let_it_be(:project) { merge_request.project }
let_it_be(:user) { create(:user) }
before do
sign_in(user)
end
context 'when a privileged user can invite in reviewer dropdown' do
before do
project.add_maintainer(user)
end
it 'shows a link for inviting members and launches invite modal' do
visit project_merge_request_path(project, merge_request)
reviewer_edit_link.click
wait_for_requests
page.within '.dropdown-menu-user' do
expect(page).to have_link('Invite Members')
expect(page).to have_selector('[data-track-event="click_invite_members"]')
expect(page).to have_selector('[data-track-label="edit_reviewer"]')
end
click_link 'Invite Members'
expect(page).to have_content("You're inviting members to the")
end
end
context 'when user cannot invite members in reviewer dropdown' do
before do
project.add_developer(user)
end
it 'shows author in assignee dropdown and no invite link' do
visit project_merge_request_path(project, merge_request)
reviewer_edit_link.click
wait_for_requests
page.within '.dropdown-menu-user' do
expect(page).not_to have_link('Invite Members')
end
end
end
def reviewer_edit_link
find('.block.reviewer .edit-link')
end
end
end
import $ from 'jquery';
import trackShowInviteMemberLink from 'ee/projects/track_invite_members';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
import trackShowInviteMemberLink from '~/sidebar/track_invite_members';
describe('Track user dropdown open', () => {
let trackingSpy;
......@@ -10,7 +10,7 @@ describe('Track user dropdown open', () => {
document.body.innerHTML = `
<div id="dummy-wrapper-element">
<div class="js-sidebar-assignee-dropdown">
<div class="js-invite-members-track" data-track-event="_track_event_">
<div class="js-invite-members-track" data-track-event="_track_event_" data-track-label="_track_label_">
</div>
</div>
</div>
......@@ -31,7 +31,7 @@ describe('Track user dropdown open', () => {
$(dropdownElement).trigger('shown.bs.dropdown');
expect(trackingSpy).toHaveBeenCalledWith(undefined, '_track_event_', {
label: 'edit_assignee',
label: '_track_label_',
});
});
});
# frozen_string_literal: true
RSpec.shared_examples 'issuable invite members experiments' do
RSpec.shared_examples 'issuable invite members' do
context 'when a privileged user can invite' do
it 'shows a link for inviting members and launches invite modal' do
before do
project.add_maintainer(user)
end
it 'shows a link for inviting members and launches invite modal' do
visit issuable_path
find('.block.assignee .edit-link').click
......@@ -23,8 +26,11 @@ RSpec.shared_examples 'issuable invite members experiments' do
end
context 'when user cannot invite members in assignee dropdown' do
it 'shows author in assignee dropdown and no invite link' do
before do
project.add_developer(user)
end
it 'shows author in assignee dropdown and no invite link' do
visit issuable_path
find('.block.assignee .edit-link').click
......
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